Mercurial > hg > octave-nkf > gnulib-hg
changeset 10182:4a177f4b083f
Add support for HP-UX ACLs.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 08 Jun 2008 19:08:22 +0200 |
parents | 5282ccc922b9 |
children | e8efce9962b0 |
files | ChangeLog lib/acl-internal.h lib/copy-acl.c lib/file-has-acl.c lib/set-mode-acl.c |
diffstat | 5 files changed, 194 insertions(+), 0 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 HP-UX ACLs. + * lib/acl-internal.h (acl_nontrivial): New declaration. + * lib/file-has-acl.c (acl_nontrivial): New function. + (file_has_acl): Add implementation using HP-UX 11 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 Cygwin ACLs.
--- a/lib/acl-internal.h +++ b/lib/acl-internal.h @@ -179,6 +179,12 @@ extern int acl_ace_nontrivial (int count, ace_t *entries); # endif +# elif HAVE_GETACL /* HP-UX */ + +/* 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_entry *entries, struct stat *sb); + # endif #endif
--- a/lib/copy-acl.c +++ b/lib/copy-acl.c @@ -392,6 +392,84 @@ # endif +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + + int count; + struct acl_entry entries[NACLENTRIES]; + int ret; + + for (;;) + { + count = (source_desc != -1 + ? fgetacl (source_desc, 0, NULL) + : getacl (src_name, 0, NULL)); + + if (count < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP) + { + count = 0; + break; + } + else + return -2; + } + + if (count == 0) + break; + + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + + if ((source_desc != -1 + ? fgetacl (source_desc, count, entries) + : getacl (src_name, 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 = (dest_desc != -1 + ? fsetacl (dest_desc, count, entries) + : setacl (dst_name, count, entries)); + if (ret < 0) + { + int saved_errno = errno; + + if (errno == ENOSYS || errno == EOPNOTSUPP) + { + struct stat source_statbuf; + + if ((source_desc != -1 + ? fstat (source_desc, &source_statbuf) + : stat (src_name, &source_statbuf)) == 0) + { + if (!acl_nontrivial (count, entries, &source_statbuf)) + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + else + saved_errno = errno; + } + + 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);
--- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -174,6 +174,27 @@ # endif +#elif USE_ACL && HAVE_GETACL /* HP-UX */ + +/* 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 (int count, struct acl_entry *entries, struct stat *sb) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl_entry *ace = &entries[i]; + + if (!((ace->uid == sb->st_uid && ace->gid == ACL_NSGROUP) + || (ace->uid == ACL_NSUSER && ace->gid == sb->st_gid) + || (ace->uid == ACL_NSUSER && ace->gid == ACL_NSGROUP))) + return 1; + } + return 0; +} + #endif @@ -371,6 +392,44 @@ return 0; # endif +# elif HAVE_GETACL /* HP-UX */ + + int count; + struct acl_entry entries[NACLENTRIES]; + + for (;;) + { + count = getacl (name, 0, NULL); + + if (count < 0) + return (errno == ENOSYS || errno == EOPNOTSUPP ? 0 : -1); + + if (count == 0) + return 0; + + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 3 entries, there cannot be only the + (uid,%), (%,gid), (%,%) entries. */ + if (count > 3) + return 1; + + if (getacl (name, count, entries) == count) + { + struct stat statbuf; + + if (stat (name, &statbuf) < 0) + return -1; + + return acl_nontrivial (count, entries, &statbuf); + } + /* Huh? The number of ACL entries changed since the last call. + Repeat. */ + } + # endif } #endif
--- a/lib/set-mode-acl.c +++ b/lib/set-mode-acl.c @@ -315,6 +315,48 @@ # endif +# elif HAVE_GETACL /* HP-UX */ + + struct stat statbuf; + struct acl_entry entries[3]; + int ret; + + if (desc != -1) + ret = fstat (desc, &statbuf); + else + ret = stat (name, &statbuf); + if (ret < 0) + return -1; + + entries[0].uid = statbuf.st_uid; + entries[0].gid = ACL_NSGROUP; + entries[0].mode = (mode >> 6) & 7; + entries[1].uid = ACL_NSUSER; + entries[1].gid = statbuf.st_gid; + entries[1].mode = (mode >> 3) & 7; + entries[2].uid = ACL_NSUSER; + entries[2].gid = ACL_NSGROUP; + entries[2].mode = mode & 7; + + if (desc != -1) + ret = fsetacl (desc, sizeof (entries) / sizeof (struct acl_entry), entries); + else + ret = setacl (name, sizeof (entries) / sizeof (struct acl_entry), entries); + if (ret < 0) + { + if (errno == ENOSYS || errno == EOPNOTSUPP) + 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