changeset 10183:e8efce9962b0

Add support for AIX ACLs.
author Bruno Haible <bruno@clisp.org>
date Sun, 08 Jun 2008 20:33:08 +0200
parents 4a177f4b083f
children 9da2345fe8f6
files ChangeLog lib/acl-internal.h lib/copy-acl.c lib/file-has-acl.c lib/set-mode-acl.c
diffstat 5 files changed, 119 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-06-08  Bruno Haible  <bruno@clisp.org>
+
+	Add support for AIX ACLs.
+	* lib/acl-internal.h (acl_nontrivial): New declaration.
+	* lib/file-has-acl.c (acl_nontrivial): New function.
+	(file_has_acl): Add implementation using AIX 4 ACL API.
+	* lib/set-mode-acl.c (qset_acl): Likewise.
+	* lib/copy-acl.c (qcopy_acl): Likewise.
+
 2008-06-08  Bruno Haible  <bruno@clisp.org>
 
 	Add support for HP-UX ACLs.
--- a/lib/acl-internal.h
+++ b/lib/acl-internal.h
@@ -185,6 +185,16 @@
    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);
 
+# elif HAVE_ACLX_GET && 0 /* AIX */
+
+/* TODO */
+
+# elif HAVE_STATACL /* older AIX */
+
+/* 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 (struct acl *a);
+
 # endif
 
 #endif
--- a/lib/copy-acl.c
+++ b/lib/copy-acl.c
@@ -470,6 +470,38 @@
     }
   return 0;
 
+#elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */
+
+  /* TODO */
+
+#elif USE_ACL && HAVE_STATACL /* older AIX */
+
+  union { struct acl a; char room[4096]; } u;
+  int ret;
+
+  if ((source_desc != -1
+       ? fstatacl (source_desc, STX_NORMAL, &u.a, sizeof (u))
+       : statacl (src_name, STX_NORMAL, &u.a, sizeof (u)))
+      < 0)
+    return -2;
+
+  ret = (dest_desc != -1
+	 ? fchacl (dest_desc, &u.a, u.a.acl_len)
+	 : chacl (dst_name, &u.a, u.a.acl_len));
+  if (ret < 0)
+    {
+      int saved_errno = errno;
+
+      chmod_or_fchmod (dst_name, dest_desc, mode);
+      errno = saved_errno;
+      return -1;
+    }
+
+  /* No need to call chmod_or_fchmod at this point, since the mode bits
+     S_ISUID, S_ISGID, S_ISVTX are also stored in the ACL.  */
+
+  return 0;
+
 #else
 
   return qset_acl (dst_name, dest_desc, mode);
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -195,6 +195,36 @@
   return 0;
 }
 
+#elif USE_ACL && HAVE_ACLX_GET && 0 /* AIX */
+
+/* TODO */
+
+#elif USE_ACL && HAVE_STATACL /* older 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_nontrivial (struct acl *a)
+{
+  /* The normal way to iterate through an ACL is like this:
+       struct acl_entry *ace;
+       for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
+         {
+           struct ace_id *aei;
+           switch (ace->ace_type)
+             {
+             case ACC_PERMIT:
+             case ACC_DENY:
+             case ACC_SPECIFY:
+               ...;
+             }
+           for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
+             ...
+         }
+   */
+  return (acl_last (a) != a->acl_ext ? 1 : 0);
+}
+
 #endif
 
 
@@ -430,12 +460,22 @@
 	     Repeat.  */
 	}
 
+# elif HAVE_ACLX_GET && 0 /* AIX */
+
+      /* TODO: use aclx_get(), and then?  */
+
+# elif HAVE_STATACL /* older AIX */
+
+      union { struct acl a; char room[4096]; } u;
+
+      if (statacl (name, STX_NORMAL, &u.a, sizeof (u)) < 0)
+	return -1;
+
+      return acl_nontrivial (&u.a);
+
 # endif
     }
 #endif
 
-  /* FIXME: Add support for AIX.  Please see Samba's
-     source/lib/sysacls.c file for fix-related ideas.  */
-
   return 0;
 }
--- a/lib/set-mode-acl.c
+++ b/lib/set-mode-acl.c
@@ -357,6 +357,31 @@
     }
   return 0;
 
+# elif HAVE_ACLX_GET && 0 /* AIX */
+
+  /* TODO: use aclx_fput or aclx_put, respectively */
+
+# elif HAVE_STATACL /* older AIX */
+
+  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 = fchacl (desc, &u.a, u.a.acl_len);
+  else
+    ret = chacl (name, &u.a, u.a.acl_len);
+
+  if (ret < 0 && errno == ENOSYS)
+    return chmod_or_fchmod (name, desc, mode);
+
+  return ret;
+
 # else /* Unknown flavor of ACLs */
   return chmod_or_fchmod (name, desc, mode);
 # endif