The acl tests still fail on AIX 5.1: file_has_acl("tmpfile0") returned no, expected yes FAIL: test-file-has-acl.sh PASS: test-set-mode-acl.sh files tmpfile0 and tmpfile2 have different access modes: 200500600 and 500600 FAIL: test-copy-acl.sh
There are two ACL APIs: one in AIX >= 5.3, one already present in AIX 4. Since I don't have access to an AIX >= 5.3 machine, I can only add support for the older API. Two things are particular about this API: - The ACL is stored in a block of memory which is traversed like a linked list. 4096 bytes of room must be allocated for it. - The ACL contains also the mode bits other than 0777 (in a special field). 2008-06-08 Bruno Haible <[EMAIL PROTECTED]> 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. *** lib/acl-internal.h.orig 2008-06-08 19:51:19.000000000 +0200 --- lib/acl-internal.h 2008-06-08 19:18:56.000000000 +0200 *************** *** 185,190 **** --- 185,200 ---- 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 *** lib/file-has-acl.c.orig 2008-06-08 19:51:19.000000000 +0200 --- lib/file-has-acl.c 2008-06-08 19:21:40.000000000 +0200 *************** *** 195,200 **** --- 195,230 ---- 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,441 **** Repeat. */ } # endif } #endif - /* FIXME: Add support for AIX. Please see Samba's - source/lib/sysacls.c file for fix-related ideas. */ - return 0; } --- 460,481 ---- 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 return 0; } *** lib/set-mode-acl.c.orig 2008-06-08 19:51:19.000000000 +0200 --- lib/set-mode-acl.c 2008-06-08 19:22:40.000000000 +0200 *************** *** 357,362 **** --- 357,387 ---- } 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 *** lib/copy-acl.c.orig 2008-06-08 19:51:19.000000000 +0200 --- lib/copy-acl.c 2008-06-08 19:51:08.000000000 +0200 *************** *** 470,475 **** --- 470,507 ---- } 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);