bug-gnulib
[Top][All Lists]
Advanced

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

Re: work in progress code - how to publish?


From: Bruno Haible
Subject: Re: work in progress code - how to publish?
Date: Sun, 27 Sep 2009 14:14:33 +0200
User-agent: KMail/1.9.9

Jim Meyering wrote on 2009-08-15:
> > may find it a good starting point for completing this support. Should I
> >   a) put into gnulib, surrounded with #if 0?
> >   b) put the code on a separate branch in gnulib?
> >   c) keep it only for myself?
> >
> > I would prefer a), so the code does not escape the attention of whoever
> > wants to continue and does not bitrot as quickly. But it goes against the
> > principle of committing only working code. What do you think?
> 
> Doing a) sounds best to me, too.

Done: I'm committing this code. Define ACL_AIX_WIP to enable it. Anyone can
continue improving it.


2009-09-27  Bruno Haible  <address@hidden>

        Disable untested support for new flavours of ACLs on AIX.
        * lib/file-has-acl.c (file_has_acl): Mark newer AIX code as work in
        progress.
        * lib/set-mode-acl.c (qset_acl): Likewise.

2008-12-07  Bruno Haible  <address@hidden>

        Add support for new flavours of ACLs on AIX. (Untested.)
        * lib/file-has-acl.c [AIX] (acl_nfs4_nontrivial): New function.
        (file_has_acl): Add support for newer AIX.
        * lib/set-mode-acl.c (qset_acl): Likewise.
        * tests/test-sameacls.c (main): Fix use of aclx_get function. Hint by
        Rainer Tammer <address@hidden>.

--- lib/file-has-acl.c.orig     2009-09-27 14:12:29.000000000 +0200
+++ lib/file-has-acl.c  2009-09-27 14:12:29.000000000 +0200
@@ -234,11 +234,7 @@
   return 0;
 }
 
-#elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */
-
-/* TODO */
-
-#elif USE_ACL && HAVE_STATACL /* older AIX */
+#elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
 
 /* Return 1 if the given ACL is non-trivial.
    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
@@ -264,6 +260,40 @@
   return (acl_last (a) != a->acl_ext ? 1 : 0);
 }
 
+# if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
+
+/* 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_nfs4_nontrivial (nfs4_acl_int_t *a)
+{
+#  if 1 /* let's try this first */
+  return (a->aclEntryN > 0 ? 1 : 0);
+#  else
+  int count = a->aclEntryN;
+  int i;
+
+  for (i = 0; i < count; i++)
+    {
+      nfs4_ace_int_t *ace = &a->aclEntry[i];
+
+      if (!((ace->flags & ACE4_ID_SPECIAL) != 0
+           && (ace->aceWho.special_whoid == ACE4_WHO_OWNER
+               || ace->aceWho.special_whoid == ACE4_WHO_GROUP
+               || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
+           && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
+           && ace->aceFlags == 0
+           && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
+                                | ACE4_WRITE_DATA | ACE4_ADD_FILE
+                                | ACE4_EXECUTE)) == 0))
+       return 1;
+    }
+  return 0;
+#  endif
+}
+
+# endif
+
 #endif
 
 
@@ -499,9 +529,65 @@
             Repeat.  */
        }
 
-# elif HAVE_ACLX_GET && 0 /* AIX */
+# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
 
-      /* TODO: use aclx_get(), and then?  */
+      acl_type_t type;
+      char aclbuf[1024];
+      void *acl = aclbuf;
+      size_t aclsize = sizeof (aclbuf);
+      mode_t mode;
+
+      for (;;)
+       {
+         /* The docs say that type being 0 is equivalent to ACL_ANY, but it
+            is not true, in AIX 5.3.  */
+         type.u64 = ACL_ANY;
+         if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
+           break;
+         if (errno != ENOSPC)
+           {
+             if (acl != aclbuf)
+               {
+                 int saved_errno = errno;
+                 free (acl);
+                 errno = saved_errno;
+               }
+             return -1;
+           }
+         aclsize = 2 * aclsize;
+         if (acl != aclbuf)
+           free (acl);
+         acl = malloc (aclsize);
+         if (acl == NULL)
+           {
+             errno = ENOMEM;
+             return -1;
+           }
+       }
+
+      if (type.u64 == ACL_AIXC)
+       {
+         int result = acl_nontrivial ((struct acl *) acl);
+         if (acl != aclbuf)
+           free (acl);
+         return result;
+       }
+      else if (type.u64 == ACL_NFS4)
+       {
+         int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
+         if (acl != aclbuf)
+           free (acl);
+         return result;
+       }
+      else
+       {
+         /* A newer type of ACL has been introduced in the system.
+            We should better support it.  */
+         if (acl != aclbuf)
+           free (acl);
+         errno = EINVAL;
+         return -1;
+       }
 
 # elif HAVE_STATACL /* older AIX */
 
--- lib/set-mode-acl.c.orig     2009-09-27 14:12:29.000000000 +0200
+++ lib/set-mode-acl.c  2009-09-27 14:12:29.000000000 +0200
@@ -445,9 +445,112 @@
     }
   return 0;
 
-# elif HAVE_ACLX_GET && 0 /* AIX */
+# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
 
-  /* TODO: use aclx_fput or aclx_put, respectively */
+  acl_type_list_t types;
+  size_t types_size = sizeof (types);
+  acl_type_t type;
+
+  if (aclx_gettypes (name, &types, &types_size) < 0
+      || types.num_entries == 0)
+    return chmod_or_fchmod (name, desc, mode);
+
+  /* XXX Do we need to clear all types of ACLs for the given file, or is it
+     sufficient to clear the first one?  */
+  type = types.entries[0];
+  if (type.u64 == ACL_AIXC)
+    {
+      union { struct acl a; char room[128]; } u;
+      int ret;
+
+      u.a.acl_len = (char *) &u.a.acl_ext[0] - (char *) &u.a; /* no entries */
+      u.a.acl_mode = mode & ~(S_IXACL | 0777);
+      u.a.u_access = (mode >> 6) & 7;
+      u.a.g_access = (mode >> 3) & 7;
+      u.a.o_access = mode & 7;
+
+      if (desc != -1)
+       ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS,
+                        type, &u.a, u.a.acl_len, mode);
+      else
+       ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS,
+                       type, &u.a, u.a.acl_len, mode);
+      if (!(ret < 0 && errno == ENOSYS))
+       return ret;
+    }
+  else if (type.u64 == ACL_NFS4)
+    {
+      union { nfs4_acl_int_t a; char room[128]; } u;
+      nfs4_ace_int_t *ace;
+      int ret;
+
+      u.a.aclVersion = NFS4_ACL_INT_STRUCT_VERSION;
+      u.a.aclEntryN = 0;
+      ace = &u.a.aclEntry[0];
+      {
+       ace->flags = ACE4_ID_SPECIAL;
+       ace->aceWho.special_whoid = ACE4_WHO_OWNER;
+       ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
+       ace->aceFlags = 0;
+       ace->aceMask =
+         (mode & 0400 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
+         | (mode & 0200
+            ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
+              | ACE4_ADD_SUBDIRECTORY
+            : 0)
+         | (mode & 0100 ? ACE4_EXECUTE : 0);
+       ace->aceWhoString[0] = '\0';
+       ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
+       ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
+       u.a.aclEntryN++;
+      }
+      {
+       ace->flags = ACE4_ID_SPECIAL;
+       ace->aceWho.special_whoid = ACE4_WHO_GROUP;
+       ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
+       ace->aceFlags = 0;
+       ace->aceMask =
+         (mode & 0040 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
+         | (mode & 0020
+            ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
+              | ACE4_ADD_SUBDIRECTORY
+            : 0)
+         | (mode & 0010 ? ACE4_EXECUTE : 0);
+       ace->aceWhoString[0] = '\0';
+       ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
+       ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
+       u.a.aclEntryN++;
+      }
+      {
+       ace->flags = ACE4_ID_SPECIAL;
+       ace->aceWho.special_whoid = ACE4_WHO_EVERYONE;
+       ace->aceType = ACE4_ACCESS_ALLOWED_ACE_TYPE;
+       ace->aceFlags = 0;
+       ace->aceMask =
+         (mode & 0004 ? ACE4_READ_DATA | ACE4_LIST_DIRECTORY : 0)
+         | (mode & 0002
+            ? ACE4_WRITE_DATA | ACE4_ADD_FILE | ACE4_APPEND_DATA
+              | ACE4_ADD_SUBDIRECTORY
+            : 0)
+         | (mode & 0001 ? ACE4_EXECUTE : 0);
+       ace->aceWhoString[0] = '\0';
+       ace->entryLen = (char *) &ace->aceWhoString[4] - (char *) ace;
+       ace = (nfs4_ace_int_t *) (char *) &ace->aceWhoString[4];
+       u.a.aclEntryN++;
+      }
+      u.a.aclLength = (char *) ace - (char *) &u.a;
+
+      if (desc != -1)
+       ret = aclx_fput (desc, SET_ACL | SET_MODE_S_BITS,
+                        type, &u.a, u.a.aclLength, mode);
+      else
+       ret = aclx_put (name, SET_ACL | SET_MODE_S_BITS,
+                       type, &u.a, u.a.aclLength, mode);
+      if (!(ret < 0 && errno == ENOSYS))
+       return ret;
+    }
+
+  return chmod_or_fchmod (name, desc, mode);
 
 # elif HAVE_STATACL /* older AIX */
 
--- tests/test-sameacls.c.orig  2009-09-27 14:12:29.000000000 +0200
+++ tests/test-sameacls.c       2009-09-27 14:12:29.000000000 +0200
@@ -447,7 +447,9 @@
   mode_t mode2;
   char text2[1000];
 
-  memset (&type1, 0, sizeof (type1)); /* type1 = ACL_ANY */
+  /* The docs say that type1 being 0 is equivalent to ACL_ANY, but it is not
+     true, in AIX 5.3.  */
+  type1.u64 = ACL_ANY;
   if (aclx_get (file1, 0, &type1, acl1, &aclsize1, &mode1) < 0)
     {
       fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
@@ -461,7 +463,9 @@
       abort ();
     }
 
-  memset (&type2, 0, sizeof (type2)); /* type2 = ACL_ANY */
+  /* The docs say that type2 being 0 is equivalent to ACL_ANY, but it is not
+     true, in AIX 5.3.  */
+  type2.u64 = ACL_ANY;
   if (aclx_get (file2, 0, &type2, acl2, &aclsize2, &mode2) < 0)
     {
       fprintf (stderr, "error accessing the ACLs of file %s\n", file2);




reply via email to

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