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. */
return (acl_last (a) != a->acl_ext ? 1 : 0);
}
+# if HAVE_ACLX_GET /* 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
Repeat. */
}
-# elif HAVE_ACLX_GET && 0 /* AIX */
+# elif HAVE_ACLX_GET /* AIX */
+
+ 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;
+ }
+ }
- /* TODO: use aclx_get(), and then? */
+ 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 */
}
return 0;
-# elif HAVE_ACLX_GET && 0 /* AIX */
+# elif HAVE_ACLX_GET /* 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 */
union { struct acl a; char room[128]; } u;
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);
abort ();
}
- memset (&type2, 0, sizeof (type2)); /* type2 = ACL_ANY */
+ /* The docs say that type1 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);