diff options
-rw-r--r-- | chacl/chacl.c | 11 | ||||
-rw-r--r-- | include/acl.h | 15 | ||||
-rw-r--r-- | libacl/acl.c | 61 | ||||
-rw-r--r-- | man/man3/acl_get_fd.3 | 20 | ||||
-rw-r--r-- | man/man3/acl_get_file.3 | 24 | ||||
-rw-r--r-- | man/man3/acl_set_compat.3 | 34 |
6 files changed, 148 insertions, 17 deletions
diff --git a/chacl/chacl.c b/chacl/chacl.c index 2807ce5..102d65c 100644 --- a/chacl/chacl.c +++ b/chacl/chacl.c @@ -84,14 +84,7 @@ main (int argc, char *argv[]) p = strrchr (argv[0], '/'); program = p != NULL ? p + 1 : argv[0]; -#ifdef HIDDEN - /* continue only if ACLs enabled */ - if (sysconf (_SC_ACL) <= 0) - { - fprintf (stderr, "%s ACLs not enabled.\n", program); - return (1); - } -#endif + acl_set_compat(ACL_COMPAT_IRIXGET); /* parse arguments */ while ((c = getopt (argc, argv, "bdlRDB")) != -1) @@ -271,7 +264,7 @@ list_acl(char *file) program, file, strerror(errno)); return 0; } - if (dacl->acl_cnt != ACL_NOT_PRESENT) { + if (dacl->acl_cnt > 0) { buf_dacl = acl_to_short_text (dacl, (ssize_t *) NULL); if (buf_dacl == NULL) { fprintf (stderr, "%s: error converting default ACL to short text " diff --git a/include/acl.h b/include/acl.h index 150c7ab..6564c52 100644 --- a/include/acl.h +++ b/include/acl.h @@ -46,7 +46,14 @@ extern "C" { #define SGI_ACL_FILE_SIZE 12 #define SGI_ACL_DEFAULT_SIZE 15 +/* + * An IRIX defined macro not in P1003.1e + * With ACL_COMPAT_IRIXGET set + * it used to signify an empty ACL. + * It is also used to delete an ACL. + */ #define ACL_NOT_PRESENT -1 + /* * Number of "base" ACL entries * (USER_OBJ, GROUP_OBJ, MASK, & OTHER_OBJ) @@ -108,14 +115,22 @@ struct acl { */ #define ACL_UNDEFINED_ID ((unsigned int)-1) +/* + * Values for acl compatibility + */ +#define ACL_COMPAT_DEFAULT 0x00 +#define ACL_COMPAT_IRIXGET 0x01 + typedef struct acl * acl_t; typedef acl_perm_t * acl_permset_t; +typedef unsigned int acl_compat_t; /* * User-space POSIX data types and functions. */ #ifndef __KERNEL__ +extern void acl_set_compat(acl_compat_t); extern int acl_add_perm(acl_permset_t, acl_perm_t); extern int acl_clear_perms(acl_permset_t); extern ssize_t acl_copy_ext(void *, acl_t, ssize_t); diff --git a/libacl/acl.c b/libacl/acl.c index 12add10..8082e53 100644 --- a/libacl/acl.c +++ b/libacl/acl.c @@ -33,7 +33,9 @@ * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ */ +#include <sys/stat.h> #include <sys/types.h> +#include <unistd.h> #include <acl.h> #include <pwd.h> #include <grp.h> @@ -56,6 +58,12 @@ #define setoserror(E) errno = (E) +/* + * Compatibility flag for IRIX functionality + * Default is to support common Linux/Posix ACL functionality + * and thus is set to zero. + */ +static acl_compat_t acl_compat = 0; static char * skip_white(char *s) @@ -565,6 +573,32 @@ acl_delete_def_file (const char *path_p) return 0; } +void +acl_set_compat(acl_compat_t compat_bits) +{ + if (compat_bits) + acl_compat |= compat_bits; + else + acl_compat = 0; +} + +static void +acl_from_mode(acl_t aclp, uid_t uid, gid_t gid, mode_t mode) +{ + aclp->acl_cnt = 3; + aclp->acl_entry[0].ae_tag = ACL_USER_OBJ; + aclp->acl_entry[0].ae_id = uid; + aclp->acl_entry[0].ae_perm = (mode & S_IRWXU) >> 6; + + aclp->acl_entry[1].ae_tag = ACL_GROUP_OBJ; + aclp->acl_entry[1].ae_id = gid; + aclp->acl_entry[1].ae_perm = (mode & S_IRWXG) >> 3; + + aclp->acl_entry[2].ae_tag = ACL_OTHER_OBJ; + aclp->acl_entry[2].ae_id = ACL_UNDEFINED_ID; + aclp->acl_entry[2].ae_perm = (mode & S_IRWXO); +} + /* * Get an ACL by file descriptor. */ @@ -584,8 +618,17 @@ acl_get_fd (int fd) free ((void *) aclp); return (NULL); } - else + else if (acl_compat & ACL_COMPAT_IRIXGET) { return aclp; + } + else { + /* copy over a minimum ACL from mode bits */ + struct stat st; + if (fstat(fd, &st) != 0) + return NULL; + acl_from_mode(aclp, st.st_uid, st.st_gid, st.st_mode); + return aclp; + } } /* @@ -625,8 +668,22 @@ acl_get_file (const char *path_p, acl_type_t type) free ((void *) aclp); return (NULL); } - else + else if (acl_compat & ACL_COMPAT_IRIXGET) { return aclp; + } + else if (type == ACL_TYPE_ACCESS) { + /* copy over a minimum ACL from mode bits */ + struct stat st; + if (stat(path_p, &st) != 0) + return NULL; + acl_from_mode(aclp, st.st_uid, st.st_gid, st.st_mode); + return aclp; + } + else { /* default ACL */ + /* empty ACL and NOT ACL_NOT_PRESENT */ + aclp->acl_cnt = 0; + return aclp; + } } /* diff --git a/man/man3/acl_get_fd.3 b/man/man3/acl_get_fd.3 index cf829f1..69bba24 100644 --- a/man/man3/acl_get_fd.3 +++ b/man/man3/acl_get_fd.3 @@ -14,6 +14,13 @@ open file referred to by \f2fd\fP. If .B _POSIX_MAC is in effect, then the process must have MAC read access to the object. +If no access ACL is associated with the \f2fd\fP, then the resultant ACL +is dependent on the ACL compatibility mode (see +.BR acl_set_compat (8) +). If \f2ACL_COMPAT_IRIXGET\f1 is +set then an ACL with a count of ACL_NOT_PRESENT is returned. Otherwise, +when no compatibility mode has been set, a mininum 3 ACE ACL based on the +file's mode is returned. .PP .I acl_set_fd sets the ACL for the open file referred to by \f2fd\fP from the \f2struct acl\fP @@ -52,7 +59,10 @@ ENOMEM allocation of the \f2struct acl\fP failed. .TP 16 ENOSYS -ACL support is not available (not installed). +ACL support is not configured in kernel. +.TP 16 +EOPNOTSUPP (ENOTSUP) +ACL support is not available for given filesystem. .PP .I acl_set_fd: .TP 16 @@ -70,7 +80,10 @@ The file system is full or some other resource needed for the ACL storage is not available. .TP 16 ENOSYS -ACL support is not available (not installed). +ACL support is not configured in kernel. +.TP 16 +EOPNOTSUPP (ENOTSUP) +ACL support is not available for given filesystem. .TP 16 EPERM The process does not have appropriate privilege to @@ -79,3 +92,6 @@ perform the operation to set the ACL. EROFS This function requires modification of a file system which is currently read-only. +.SH SEE ALSO +.BR acl_get_file (8), +.BR acl_set_compat (8). diff --git a/man/man3/acl_get_file.3 b/man/man3/acl_get_file.3 index 47fb7b5..95ce798 100644 --- a/man/man3/acl_get_file.3 +++ b/man/man3/acl_get_file.3 @@ -12,11 +12,18 @@ acl_get_file, acl_set_file \- get or set the ACL for a pathname returns a pointer to an allocated \f2struct acl\fP associated with the pathname pointed to by \f2path\fP. \f2type\fP determines whether the default ACL (\f2type == ACL_TYPE_DEFAULT\fP) or access ACL (\f2type == ACL_TYPE_ACCESS\fP) is returned. The default ACL is available only for directories. -If there is no default ACL associated with the specified directory, an -ACL containing zero entries is returned. If .B _POSIX_MAC is in effect, then the process must have MAC read access to the object. +If no ACL is associated with the \f2path\fP, then the resultant ACL +is dependent on the ACL compatibility mode (see +.BR acl_set_compat (8) +). If \f2ACL_COMPAT_IRIXGET\f1 is +set then an ACL with a count of ACL_NOT_PRESENT is returned. +If no compatibility mode has been set and the ACL is an access ACL then +a mininum 3 ACE ACL based on the file's mode is returned. +If no compatibility mode has been set and the ACL is a default ACL then +an ACL with a count of zero entries is returned. .PP .I acl_set_file sets the ACL of the specified pathname. \f2type\fP indicates which ACL, @@ -63,7 +70,10 @@ ENOMEM allocation of the \f2struct acl\fP failed. .TP 16 ENOSYS -ACL support is not available (not installed). +ACL support is not configured in kernel. +.TP 16 +EOPNOTSUPP (ENOTSUP) +ACL support is not available for given filesystem. .TP 16 ENOTDIR A component of the path prefix is not a directory. @@ -91,7 +101,10 @@ The file system is full or some other resource needed for the ACL storage is not available. .TP 16 ENOSYS -ACL support is not available (not installed). +ACL support is not configured in kernel. +.TP 16 +EOPNOTSUPP (ENOTSUP) +ACL support is not available for given filesystem. .TP 16 ENOTDIR A component of the path prefix is not a directory. @@ -103,3 +116,6 @@ perform the operation to set the ACL. EROFS This function requires modification of a file system which is currently read-only. +.SH SEE ALSO +.BR acl_get_fd (8), +.BR acl_set_compat (8). diff --git a/man/man3/acl_set_compat.3 b/man/man3/acl_set_compat.3 new file mode 100644 index 0000000..8cc8530 --- /dev/null +++ b/man/man3/acl_set_compat.3 @@ -0,0 +1,34 @@ +.TH ACL_SET_COMPAT 3 +.SH NAME +acl_set_compat \- set compatibility mode for ACL library +.SH SYNOPSIS +.B #include <acl/acl.h> +.PP +.B void acl_set_compat(acl_compat_t compat_bits); +.SH DESCRIPTION +.I acl_set_compat +sets the compatibility mode for various IRIX and Linux ACL functionality. +The ACL semantics for IRIX even though they are based on the Posix 1003.1e +withdrawn ACL standard, are subtly different from the semantics of +ext2 ACLs and BSD ACLs. The default semantics used are that of the ext2 +Posix ACLs and a call to this function should only be made to gain +IRIX compatibility. +.PP +\f2Compat_bits\f1 is a bit-vector formed by or'ing compatiblity macros +with the prefix of \f2ACL_COMPAT_\f1. Each call to this function will +add to the current compatibility vector. Given a \f2compat_bits\f1 value +of zero will reset it. +If \f2compat_bits\f1 is set to \f2ACL_COMPAT_IRIXGET\f1 then the semantics for +.BR acl_get_fd (8) +and +.BR acl_get_file (8) +are changed in the cases where no ACL was ever explicitly set for +a file or directory. +Please refer to +.BR acl_get_fd (8) +and +.BR acl_get_file (8) +for a description of the differing semantics. +.SH SEE ALSO +.BR acl_get_fd (8), +.BR acl_get_file (8). |