diff -urNp current/lib/libc/posix1e/Makefile.inc nfs4acl/lib/libc/posix1e/Makefile.inc --- current/lib/libc/posix1e/Makefile.inc 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/Makefile.inc 2009-05-23 08:37:49.000000000 +0200 @@ -4,52 +4,74 @@ CFLAGS+=-D_ACL_PRIVATE -SRCS+= acl_calc_mask.c \ +# Copy kern/subr_acl_nfs4.c to the libc object directory. +subr_acl_nfs4.c: ${.CURDIR}/../../sys/kern/subr_acl_nfs4.c + cat ${.ALLSRC} > ${.TARGET} + +SRCS+= acl_branding.c \ + acl_calc_mask.c \ acl_copy.c \ acl_compat.c \ acl_delete.c \ acl_delete_entry.c \ acl_entry.c \ + acl_flag.c \ acl_free.c \ acl_from_text.c \ + acl_from_text_nfs4.c \ acl_get.c \ acl_init.c \ acl_perm.c \ acl_set.c \ + acl_strip.c \ acl_support.c \ + acl_support_nfs4.c \ acl_to_text.c \ + acl_to_text_nfs4.c \ acl_valid.c \ extattr.c \ mac.c \ mac_exec.c \ mac_get.c \ - mac_set.c + mac_set.c \ + subr_acl_nfs4.c SYM_MAPS+=${.CURDIR}/posix1e/Symbol.map MAN+= acl.3 \ + acl_add_flag_np.3 \ acl_add_perm.3 \ acl_calc_mask.3 \ + acl_clear_flags_np.3 \ acl_clear_perms.3 \ acl_copy_entry.3 \ acl_create_entry.3 \ acl_delete.3 \ acl_delete_entry.3 \ + acl_delete_flag_np.3 \ acl_delete_perm.3 \ acl_dup.3 \ acl_free.3 \ acl_from_text.3 \ acl_get.3 \ + acl_get_brand_np.3 \ acl_get_entry.3 \ + acl_get_entry_type_np.3 \ + acl_get_flagset_np.3 \ + acl_get_flag_np.3 \ acl_get_permset.3 \ acl_get_perm_np.3 \ acl_get_qualifier.3 \ acl_get_tag_type.3 \ acl_init.3 \ + acl_is_trivial_np.3 \ acl_set.3 \ + acl_set_entry_type_np.3 \ + acl_set_flagset_np.3 \ acl_set_permset.3 \ acl_set_qualifier.3 \ acl_set_tag_type.3 \ + acl_strip_np.3 \ acl_to_text.3 \ acl_valid.3 \ extattr.3 \ @@ -63,15 +85,18 @@ MAN+= acl.3 \ mac_text.3 \ posix1e.3 -MLINKS+=acl_delete.3 acl_delete_def_file.3 \ +MLINKS+=acl_create_entry.3 acl_create_entry_np.3\ + acl_delete.3 acl_delete_def_file.3 \ acl_delete.3 acl_delete_file_np.3 \ acl_delete.3 acl_delete_fd_np.3 \ + acl_delete_entry.3 acl_delete_entry_np.3\ acl_get.3 acl_get_file.3 \ acl_get.3 acl_get_fd.3 \ acl_get.3 acl_get_fd_np.3 \ acl_set.3 acl_set_file.3 \ acl_set.3 acl_set_fd.3 \ acl_set.3 acl_set_fd_np.3 \ + acl_to_text.3 acl_to_text_np.3 \ acl_valid.3 acl_valid_file_np.3 \ acl_valid.3 acl_valid_fd_np.3 \ extattr.3 extattr_namespace_to_string.3 \ diff -urNp current/lib/libc/posix1e/Symbol.map nfs4acl/lib/libc/posix1e/Symbol.map --- current/lib/libc/posix1e/Symbol.map 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/Symbol.map 2009-05-25 19:14:28.000000000 +0200 @@ -66,7 +66,21 @@ FBSD_1.0 { }; FBSD_1.1 { + acl_add_flag_np; acl_add_perm; + acl_clear_flags_np; + acl_create_entry_np; + acl_delete_entry_np; + acl_delete_flag_np; acl_delete_perm; + acl_get_brand_np; + acl_get_entry_type_np; + acl_get_flag_np; + acl_get_flagset_np; acl_get_perm_np; + acl_is_trivial_np; + acl_set_entry_type_np; + acl_set_flagset_np; + acl_strip_np; + acl_to_text_np; }; diff -urNp current/lib/libc/posix1e/acl.3 nfs4acl/lib/libc/posix1e/acl.3 --- current/lib/libc/posix1e/acl.3 2009-05-23 17:12:25.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl.3 2009-05-23 17:18:23.000000000 +0200 @@ -59,6 +59,10 @@ all of these support routines are implem .Pp Available functions, sorted by behavior, include: .Bl -tag -width indent +.It Fn acl_add_flag_np +This function is described in +.Xr acl_add_flag_np 3 , +and may be used to add flags to a flagset. .It Fn acl_add_perm This function is described in .Xr acl_add_perm 3 , @@ -70,6 +74,10 @@ and may be used to calculate and set the the .Dv ACL_MASK entry. +.It Fn acl_clear_flags_np +This function is described in +.Xr acl_clear_flags_np 3 , +and may be used to clear all flags from a flagset. .It Fn acl_clear_perms This function is described in .Xr acl_clear_perms 3 , @@ -78,8 +86,11 @@ and may be used to clear all permissions This function is described in .Xr acl_copy_entry 3 , and may be used to copy the contents of an ACL entry. -.It Fn acl_create_entry -This function is described in +.It Xo +.Fn acl_create_entry , +.Fn acl_create_entry_np +.Xc +These functions are described in .Xr acl_create_entry 3 , and may be used to create an empty entry in an ACL. .It Xo @@ -92,10 +103,17 @@ and may be used to create an empty entry These functions are described in .Xr acl_delete 3 , and may be used to delete ACLs from file system objects. -.It Fn acl_delete_entry -This function is described in +.It Xo +.Fn acl_delete_entry , +.Fn acl_delete_entry_np , +.Xc +This functions are described in .Xr acl_delete_entry 3 , and may be used to delete an entry from an ACL. +.It Fn acl_delete_flag_np +This function is described in +.Xr acl_delete_flag_np 3 , +and may be used to delete flags from a flagset. .It Fn acl_delete_perm This function is described in .Xr acl_delete_perm 3 , @@ -126,6 +144,14 @@ and may be used to retrieve a designated These functions are described in .Xr acl_get 3 , and may be used to retrieve ACLs from file system objects. +.It Fn acl_get_entry_type_np +This function is described in +.Xr acl_get_entry_type_np 3 , +and may be used to retrieve an ACL type from an ACL entry. +.It Fn acl_get_flagset_np +This function is described in +.Xr acl_get_flagset_np 3 , +and may be used to retrieve a flagset from an ACL entry. .It Fn acl_get_permset This function is described in .Xr acl_get_permset 3 , @@ -142,6 +168,10 @@ and may be used to retrieve the tag type This function is described in .Xr acl_init 3 , and may be used to allocate a fresh (empty) ACL structure. +.It Fn acl_is_trivial_np +This function is described in +.Xr acl_is_trivial_np 3 , +and may be used to find out whether ACL is trivial. .It Xo .Fn acl_set_fd , .Fn acl_set_fd_np , @@ -151,6 +181,14 @@ and may be used to allocate a fresh (emp These functions are described in .Xr acl_set 3 , and may be used to assign an ACL to a file system object. +.It Fn acl_set_entry_type_np +This function is described in +.Xr acl_set_entry_type_np 3 , +and may be used to set the ACL type of an ACL entry. +.It Fn acl_set_flagset_np +This function is described in +.Xr acl_set_flagset_np 3 , +and may be used to set the flags of an ACL entry from a flagset. .It Fn acl_set_permset This function is described in .Xr acl_set_permset 3 , @@ -163,8 +201,15 @@ and may be used to set the qualifier of This function is described in .Xr acl_set_tag_type 3 , and may be used to set the tag type of an ACL. -.It Fn acl_to_text -This function is described in +.It Fn acl_strip_np +This function is describe din +.Xr acl-strip_np 3 , +and may be used to remove extended entries from an ACL. +.It Xo +.Fn acl_to_text , +.Fn acl_to_text_np +.Xc +These functions are described in .Xr acl_to_text 3 , and may be used to generate a text-form of a POSIX.1e semantics ACL. .It Xo @@ -189,25 +234,34 @@ library. .Sh SEE ALSO .Xr getfacl 1 , .Xr setfacl 1 , +.Xr acl_add_flag_np 3 , .Xr acl_add_perm 3 , .Xr acl_calc_mask 3 , +.Xr acl_clear_flags_np 3 , .Xr acl_clear_perms 3 , .Xr acl_copy_entry 3 , .Xr acl_create_entry 3 , .Xr acl_delete_entry 3 , +.Xr acl_delete_flag_np 3 , .Xr acl_delete_perm 3 , .Xr acl_dup 3 , .Xr acl_free 3 , .Xr acl_from_text 3 , .Xr acl_get 3 , +.Xr acl_get_entry_type_np 3 , +.Xr acl_get_flagset_np 3 , .Xr acl_get_permset 3 , .Xr acl_get_qualifier 3 , .Xr acl_get_tag_type 3 , .Xr acl_init 3 , +.Xr acl_is_trivial_np 3 , .Xr acl_set 3 , +.Xr acl_set_entry_type_np 3 , +.Xr acl_set_flagset_np 3 , .Xr acl_set_permset 3 , .Xr acl_set_qualifier 3 , .Xr acl_set_tag_type 3 , +.Xr acl_strip_np 3 , .Xr acl_to_text 3 , .Xr acl_valid 3 , .Xr posix1e 3 , diff -urNp current/lib/libc/posix1e/acl_add_flag_np.3 nfs4acl/lib/libc/posix1e/acl_add_flag_np.3 --- current/lib/libc/posix1e/acl_add_flag_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_add_flag_np.3 2009-05-24 21:07:38.000000000 +0200 @@ -0,0 +1,98 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_ADD_FLAG_NP 3 +.Os +.Sh NAME +.Nm acl_add_flag_np +.Nd add flags to a flagset +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_add_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag" +.Sh DESCRIPTION +The +.Fn acl_add_flag_np +function +is a non-portable call that adds the flags contained in +.Fa flags +to the flagset +.Fa flagset_d . +.Pp +Note: it is not considered an error to attempt to add flags +that already exist in the flagset. +.Pp +Valid values are: +.Pp +.Bl -column -offset 3n "ACL_ENTRY_NO_PROPAGATE_INHERIT" +.It ACL_ENTRY_FILE_INHERIT Will be inherited by files. +.It ACL_ENTRY_DIRECTORY_INHERIT Will be inherited by directories. +.It ACL_ENTRY_NO_PROPAGATE_INHERIT Will not propagate. +.It ACL_ENTRY_INHERIT_ONLY Inherit-only. +.El +.Sh RETURN VALUES +.Rv -std acl_add_flag_np +.Sh ERRORS +The +.Fn acl_add_flag_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa flagset_d +is not a valid descriptor for a flagset within an ACL entry. +Argument +.Fa flag +does not contain a valid +.Vt acl_flag_t +value. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_clear_flags_np 3 , +.Xr acl_delete_flag_np 3 , +.Xr acl_get_flagset_np 3 , +.Xr acl_set_flagset_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_add_flag_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_add_flag_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_add_perm.3 nfs4acl/lib/libc/posix1e/acl_add_perm.3 --- current/lib/libc/posix1e/acl_add_perm.3 2009-05-23 17:12:25.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_add_perm.3 2009-05-26 17:15:43.000000000 +0200 @@ -52,11 +52,43 @@ that already exist in the permission set .Pp For POSIX.1e ACLs, valid values are: .Pp -.Bl -column -offset 3n "ACL_EXECUTE" +.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS" .It ACL_EXECUTE Execute permission .It ACL_WRITE Write permission .It ACL_READ Read permission .El +.Pp +For NFSv4 ACLs, valid values are: +.Pp +.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS" +.It ACL_READ_DATA Read permission +.It ACL_LIST_DIRECTORY Same as ACL_READ_DATA +.It ACL_WRITE_DATA Write permission, or permission to create files +.It ACL_ADD_FILE Same as ACL_READ_DATA +.It ACL_APPEND_DATA Permission to create directories. Ignored for files +.It ACL_ADD_SUBDIRECTORY Same as ACL_APPEND_DATA +.It ACL_READ_NAMED_ATTRS Ignored +.It ACL_WRITE_NAMED_ATTRS Ignored +.It ACL_EXECUTE Execute permission +.It ACL_DELETE_CHILD Permission to delete files and subdirectories +.It ACL_READ_ATTRIBUTES Permission to read basic attributes +.It ACL_WRITE_ATTRIBUTES Permission to change basic attributes +.It ACL_DELETE Permission to delete the object this ACL is placed on +.It ACL_READ_ACL Permission to read ACL +.It ACL_WRITE_ACL Permission to change the ACL and file mode +.It ACL_SYNCHRONIZE Ignored +.El +.Pp +Calling +.Fn acl_add_perm +with +.Fa perm +equal to ACL_WRITE or ACL_READ brands the ACL as POSIX. +Calling it with ACL_READ_DATA, ACL_LIST_DIRECTORY, ACL_WRITE_DATA, +ACL_ADD_FILE, ACL_APPEND_DATA, ACL_ADD_SUBDIRECTORY, ACL_READ_NAMED_ATTRS, +ACL_WRITE_NAMED_ATTRS, ACL_DELETE_CHILD, ACL_READ_ATTRIBUTES, +ACL_WRITE_ATTRIBUTES, ACL_DELETE, ACL_READ_ACL, ACL_WRITE_ACL +or ACL_SYNCHRONIZE brands the ACL as NFSv4. .Sh RETURN VALUES .Rv -std acl_add_perm .Sh ERRORS @@ -73,11 +105,13 @@ Argument does not contain a valid .Vt acl_perm_t value. +ACL is already branded differently. .El .Sh SEE ALSO .Xr acl 3 , .Xr acl_clear_perms 3 , .Xr acl_delete_perm 3 , +.Xr acl_get_brand_np 3 , .Xr acl_get_permset 3 , .Xr acl_set_permset 3 , .Xr posix1e 3 diff -urNp current/lib/libc/posix1e/acl_branding.c nfs4acl/lib/libc/posix1e/acl_branding.c --- current/lib/libc/posix1e/acl_branding.c 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_branding.c 2009-05-26 18:53:59.000000000 +0200 @@ -0,0 +1,166 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "acl_support.h" + +/* + * An ugly detail of the implementation - fortunately not visible + * to the API users - is the "branding": libc needs to keep track + * of what "brand" ACL is: NFSv4, POSIX.1e or unknown. It happens + * automatically - for example, during acl_get_file(3) ACL gets + * branded according to the "type" argument; during acl_set_permset + * ACL, if its brand is unknown it gets branded as NFSv4 if any of the + * NFSv4 permissions that are not valid for POSIX.1e ACL are set etc. + * Branding information is used for printing out the ACL (acl_to_text(3)), + * veryfying acl_set_whatever arguments (checking against setting + * bits that are valid only for NFSv4 in ACL branded as POSIX.1e) etc. + */ + +static acl_t +entry2acl(acl_entry_t entry) +{ + acl_t aclp; + + aclp = (acl_t)(((long)entry >> _ACL_T_ALIGNMENT_BITS) << _ACL_T_ALIGNMENT_BITS); + + return (aclp); +} + +/* + * Return brand of an ACL. + */ +int +_acl_brand(const acl_t acl) +{ + + return (acl->ats_brand); +} + +int +_entry_brand(const acl_entry_t entry) +{ + + return (_acl_brand(entry2acl(entry))); +} + +/* + * Return 1, iff branding ACL as "brand" is ok. + */ +int +_acl_brand_may_be(const acl_t acl, int brand) +{ + + if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) + return (1); + + if (_acl_brand(acl) == brand) + return (1); + + return (0); +} + +int +_entry_brand_may_be(const acl_entry_t entry, int brand) +{ + + return (_acl_brand_may_be(entry2acl(entry), brand)); +} + +/* + * Brand ACL as "brand". + */ +void +_acl_brand_as(acl_t acl, int brand) +{ + + assert(_acl_brand_may_be(acl, brand)); + + acl->ats_brand = brand; +} + +void +_entry_brand_as(const acl_entry_t entry, int brand) +{ + + _acl_brand_as(entry2acl(entry), brand); +} + +int +_acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type) +{ + + switch (_acl_brand(acl)) { + case ACL_BRAND_NFS4: + if (type == ACL_TYPE_NFS4) + return (0); + break; + + case ACL_BRAND_POSIX: + if (type == ACL_TYPE_ACCESS || type == ACL_TYPE_DEFAULT) + return (0); + break; + } + + return (-1); +} + +void +_acl_brand_from_type(acl_t acl, acl_type_t type) +{ + + switch (type) { + case ACL_TYPE_NFS4: + _acl_brand_as(acl, ACL_BRAND_NFS4); + break; + case ACL_TYPE_ACCESS: + case ACL_TYPE_DEFAULT: + _acl_brand_as(acl, ACL_BRAND_POSIX); + break; + default: + /* XXX: What to do here? */ + break; + } +} + +int +acl_get_brand_np(acl_t acl, int *brand_p) +{ + + if (acl == NULL || brand_p == NULL) { + errno = EINVAL; + return (-1); + } + *brand_p = _acl_brand(acl); + + return (0); +} diff -urNp current/lib/libc/posix1e/acl_calc_mask.c nfs4acl/lib/libc/posix1e/acl_calc_mask.c --- current/lib/libc/posix1e/acl_calc_mask.c 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_calc_mask.c 2009-05-25 19:30:06.000000000 +0200 @@ -35,6 +35,8 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include +#include "acl_support.h" + /* * acl_calc_mask() (23.4.2): calculate and set the permissions * associated with the ACL_MASK ACL entry. If the ACL already @@ -48,6 +50,12 @@ acl_calc_mask(acl_t *acl_p) acl_t acl_new; int i, mask_mode, mask_num; + if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) { + errno = EINVAL; + return (-1); + } + _acl_brand_as(*acl_p, ACL_BRAND_POSIX); + /* * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL. * Since one of the primary reasons to use this function would be diff -urNp current/lib/libc/posix1e/acl_clear_flags_np.3 nfs4acl/lib/libc/posix1e/acl_clear_flags_np.3 --- current/lib/libc/posix1e/acl_clear_flags_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_clear_flags_np.3 2009-05-24 21:07:38.000000000 +0200 @@ -0,0 +1,79 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_CLEAR_FLAGS_NP 3 +.Os +.Sh NAME +.Nm acl_clear_flags_np +.Nd clear flags from a flagset +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_clear_flags_np "acl_flagset_t flagset_d" +.Sh DESCRIPTION +The +.Fn acl_clear_flags_np +function +is a non-portable call that clears all flags from flagset +.Fa flagset_d . +.Sh RETURN VALUES +.Rv -std acl_clear_flags_np +.Sh ERRORS +The +.Fn acl_clear_flags_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa flagset_d +is not a valid descriptor for a flagset. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_add_flag_np 3 , +.Xr acl_delete_flag_np 3 , +.Xr acl_get_flagset_np 3 , +.Xr acl_set_flagset_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_clear_flags_np +function was added in +.Fx 5.0 . +.Sh AUTHORS +The +.Fn acl_clear_flags_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_copy.c nfs4acl/lib/libc/posix1e/acl_copy.c --- current/lib/libc/posix1e/acl_copy.c 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_copy.c 2009-05-23 08:37:49.000000000 +0200 @@ -35,6 +35,8 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include +#include "acl_support.h" + /* * acl_copy_entry() (23.4.4): copy the contents of ACL entry src_d to * ACL entry dest_d @@ -48,9 +50,21 @@ acl_copy_entry(acl_entry_t dest_d, acl_e return (-1); } - dest_d->ae_tag = src_d->ae_tag; - dest_d->ae_id = src_d->ae_id; + /* + * Can we brand the new entry the same as the source entry? + */ + if (!_entry_brand_may_be(dest_d, _entry_brand(src_d))) { + errno = EINVAL; + return (-1); + } + + _entry_brand_as(dest_d, _entry_brand(src_d)); + + dest_d->ae_tag = src_d->ae_tag; + dest_d->ae_id = src_d->ae_id; dest_d->ae_perm = src_d->ae_perm; + dest_d->ae_entry_type = src_d->ae_entry_type; + dest_d->ae_flags = src_d->ae_flags; return (0); } diff -urNp current/lib/libc/posix1e/acl_create_entry.3 nfs4acl/lib/libc/posix1e/acl_create_entry.3 --- current/lib/libc/posix1e/acl_create_entry.3 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_create_entry.3 2009-04-29 09:35:23.000000000 +0200 @@ -30,6 +30,7 @@ .Os .Sh NAME .Nm acl_create_entry +.Nm acl_create_entry_np .Nd create a new ACL entry .Sh LIBRARY .Lb libc @@ -38,6 +39,8 @@ .In sys/acl.h .Ft int .Fn acl_create_entry "acl_t *acl_p" "acl_entry_t *entry_p" +.Ft int +.Fn acl_create_entry_np "acl_t *acl_p" "acl_entry_t *entry_p" "int index" .Sh DESCRIPTION The .Fn acl_create_entry @@ -45,6 +48,16 @@ function is a POSIX.1e call that creates a new ACL entry in the ACL pointed to by .Fa acl_p . +The +.Fn acl_create_entry_np +function is a non-portable version that creates the ACL entry +at position +.Fa index . +Positions are numbered starting from zero, i.e. calling +.Fn acl_create_entry_np +with +.Fa index +argument equal to zero will prepend the entry to the ACL. .Sh RETURN VALUES .Rv -std acl_create_entry .Sh ERRORS @@ -56,6 +69,9 @@ function fails if: Argument .Fa acl_p does not point to a pointer to a valid ACL. +Argument +.Fa index +is out of bounds. .It Bq Er ENOMEM The ACL working storage requires more memory than is allowed by the hardware or system-imposed memory diff -urNp current/lib/libc/posix1e/acl_delete_entry.3 nfs4acl/lib/libc/posix1e/acl_delete_entry.3 --- current/lib/libc/posix1e/acl_delete_entry.3 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_delete_entry.3 2009-04-29 09:35:23.000000000 +0200 @@ -29,7 +29,8 @@ .Dt ACL_DELETE_ENTRY 3 .Os .Sh NAME -.Nm acl_delete_entry +.Nm acl_delete_entry , +.Nm acl_delete_entry_np , .Nd delete an ACL entry from an ACL .Sh LIBRARY .Lb libc @@ -38,6 +39,8 @@ .In sys/acl.h .Ft int .Fn acl_delete_entry "acl_t acl" "acl_entry_t entry_d" +.Ft int +.Fn acl_delete_entry_np "acl_t acl" "int index" .Sh DESCRIPTION The .Fn acl_delete_entry @@ -46,6 +49,18 @@ is a POSIX.1e call that removes the ACL .Fa entry_d from ACL .Fa acl . +The +.Fn acl_delete_entry_np +function is a non-portable version that removes the ACL entry +at position +.Fa index +from ACL +.Fa acl . +Positions are numbered starting from zero, i.e. calling +.Fn acl_delete_entry_np +with +.Fa index +argument equal to zero will remove the first ACL entry. .Sh RETURN VALUES .Rv -std acl_delete_entry .Sh ERRORS @@ -61,6 +76,9 @@ Argument .Fa entry_d is not a valid descriptor for an ACL entry in .Fa acl . +Argument +.Fa index +is out of bounds. .El .Sh SEE ALSO .Xr acl 3 , diff -urNp current/lib/libc/posix1e/acl_delete_entry.c nfs4acl/lib/libc/posix1e/acl_delete_entry.c --- current/lib/libc/posix1e/acl_delete_entry.c 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_delete_entry.c 2009-05-25 19:30:06.000000000 +0200 @@ -33,6 +33,39 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include "un-namespace.h" #include #include +#include + +#include "acl_support.h" + +static int +_entry_matches(const acl_entry_t a, const acl_entry_t b) +{ + /* + * There is a semantical difference here between NFSv4 and POSIX + * draft ACLs. In POSIX, there may be only one entry for the particular + * user or group. In NFSv4 ACL, there may be any number of them. We're + * trying to be more specific here in that case. + */ + switch (_entry_brand(a)) { + case ACL_BRAND_NFS4: + if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type) + return (0); + + /* If ae_ids matter, compare them as well. */ + if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) { + if (a->ae_id != b->ae_id) + return (0); + } + + return (1); + + default: + if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id)) + return (1); + } + + return (0); +} /* * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d @@ -42,7 +75,7 @@ int acl_delete_entry(acl_t acl, acl_entry_t entry_d) { struct acl *acl_int; - int i; + int i, j, found = 0; if (acl == NULL || entry_d == NULL) { errno = EINVAL; @@ -51,29 +84,74 @@ acl_delete_entry(acl_t acl, acl_entry_t acl_int = &acl->ats_acl; + if (_entry_brand(entry_d) != _acl_brand(acl)) { + errno = EINVAL; + return (-1); + } + if ((acl->ats_acl.acl_cnt < 1) || (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) { errno = EINVAL; return (-1); } - for (i = 0; i < acl->ats_acl.acl_cnt; i++) { - /* if this is our entry... */ - if ((acl->ats_acl.acl_entry[i].ae_tag == entry_d->ae_tag) && - (acl->ats_acl.acl_entry[i].ae_id == entry_d->ae_id)) { + for (i = 0; i < acl->ats_acl.acl_cnt;) { + if (_entry_matches(&(acl->ats_acl.acl_entry[i]), entry_d)) { /* ...shift the remaining entries... */ - for (; i < acl->ats_acl.acl_cnt - 1; ++i) - acl->ats_acl.acl_entry[i] = - acl->ats_acl.acl_entry[i+1]; + for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j) + acl->ats_acl.acl_entry[j] = + acl->ats_acl.acl_entry[j+1]; /* ...drop the count and zero the unused entry... */ acl->ats_acl.acl_cnt--; - bzero(&acl->ats_acl.acl_entry[i], + bzero(&acl->ats_acl.acl_entry[j], sizeof(struct acl_entry)); acl->ats_cur_entry = 0; - return (0); - } + + /* Continue with the loop to remove all maching entries. */ + found = 1; + } else + i++; } + if (found) + return (0); errno = EINVAL; return (-1); } + +int +acl_delete_entry_np(acl_t acl, int offset) +{ + struct acl *acl_int; + int i; + + if (acl == NULL) { + errno = EINVAL; + return (-1); + } + + acl_int = &acl->ats_acl; + + if (offset < 0 || offset >= acl_int->acl_cnt) { + errno = EINVAL; + return (-1); + } + + if ((acl->ats_acl.acl_cnt < 1) || + (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) { + errno = EINVAL; + return (-1); + } + + /* ...shift the remaining entries... */ + for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i) + acl->ats_acl.acl_entry[i] = + acl->ats_acl.acl_entry[i+1]; + /* ...drop the count and zero the unused entry... */ + acl->ats_acl.acl_cnt--; + bzero(&acl->ats_acl.acl_entry[i], + sizeof(struct acl_entry)); + acl->ats_cur_entry = 0; + + return (0); +} diff -urNp current/lib/libc/posix1e/acl_delete_flag_np.3 nfs4acl/lib/libc/posix1e/acl_delete_flag_np.3 --- current/lib/libc/posix1e/acl_delete_flag_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_delete_flag_np.3 2009-05-24 21:07:38.000000000 +0200 @@ -0,0 +1,84 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_DELETE_FLAG_NP 3 +.Os +.Sh NAME +.Nm acl_delete_flag_np +.Nd delete flags from a flagset +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_delete_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag" +.Sh DESCRIPTION +The +.Fn acl_delete_flag_np +function +is a non-portable call that removes specific flags from flagset +.Fa flags . +.Sh RETURN VALUES +.Rv -std acl_delete_flag_np +.Sh ERRORS +The +.Fn acl_delete_flag_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa flagset_d +is not a valid descriptor for a flagset. +Argument +.Fa flag +does not contain a valid +.Vt acl_flag_t +value. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_add_flag_np 3 , +.Xr acl_clear_flag_nps 3 , +.Xr acl_get_flagset_np 3 , +.Xr acl_set_flagset_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_delete_flag_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_delete_flag_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_entry.c nfs4acl/lib/libc/posix1e/acl_entry.c --- current/lib/libc/posix1e/acl_entry.c 2009-05-29 19:54:13.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_entry.c 2009-05-29 20:25:32.000000000 +0200 @@ -74,6 +74,48 @@ acl_create_entry(acl_t *acl_p, acl_entry return (0); } +int +acl_create_entry_np(acl_t *acl_p, acl_entry_t *entry_p, int offset) +{ + int i; + struct acl *acl_int; + + if (acl_p == NULL) { + errno = EINVAL; + return (-1); + } + + acl_int = &(*acl_p)->ats_acl; + + if ((acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) || (acl_int->acl_cnt < 0)) { + errno = EINVAL; + return (-1); + } + + if (offset < 0 || offset >= acl_int->acl_cnt) { + errno = EINVAL; + return (-1); + } + + /* Make room for the new entry. */ + for (i = acl_int->acl_cnt; i > offset; i--) + acl_int->acl_entry[i] = acl_int->acl_entry[i - 1]; + + acl_int->acl_cnt++; + + *entry_p = &acl_int->acl_entry[offset]; + + (**entry_p).ae_tag = ACL_UNDEFINED_TAG; + (**entry_p).ae_id = ACL_UNDEFINED_ID; + (**entry_p).ae_perm = ACL_PERM_NONE; + (**entry_p).ae_entry_type = 0; + (**entry_p).ae_flags= 0; + + (*acl_p)->ats_cur_entry = 0; + + return (0); +} + /* * acl_get_entry() (23.4.14): returns an ACL entry from an ACL * indicated by entry_id. diff -urNp current/lib/libc/posix1e/acl_flag.c nfs4acl/lib/libc/posix1e/acl_flag.c --- current/lib/libc/posix1e/acl_flag.c 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_flag.c 2009-05-26 11:21:36.000000000 +0200 @@ -0,0 +1,155 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include "acl_support.h" + +static int +_flag_is_invalid(acl_flag_t flag) +{ + + if ((flag & ACL_FLAGS_BITS) == flag) + return (0); + + errno = EINVAL; + + return (1); +} + +int +acl_add_flag_np(acl_flagset_t flagset_d, acl_flag_t flag) +{ + + if (flagset_d == NULL) { + errno = EINVAL; + return (-1); + } + + if (_flag_is_invalid(flag)) + return (-1); + + *flagset_d |= flag; + + return (0); +} + +int +acl_clear_flags_np(acl_flagset_t flagset_d) +{ + + if (flagset_d == NULL) { + errno = EINVAL; + return (-1); + } + + *flagset_d |= 0; + + return (0); +} + +int +acl_delete_flag_np(acl_flagset_t flagset_d, acl_flag_t flag) +{ + + if (flagset_d == NULL) { + errno = EINVAL; + return (-1); + } + + if (_flag_is_invalid(flag)) + return (-1); + + *flagset_d &= ~flag; + + return (0); +} + +int +acl_get_flag_np(acl_flagset_t flagset_d, acl_flag_t flag) +{ + + if (flagset_d == NULL) { + errno = EINVAL; + return (-1); + } + + if (_flag_is_invalid(flag)) + return (-1); + + if (*flagset_d & flag) + return (1); + + return (0); +} + +int +acl_get_flagset_np(acl_entry_t entry_d, acl_flagset_t *flagset_p) +{ + + if (entry_d == NULL || flagset_p == NULL) { + errno = EINVAL; + return (-1); + } + + if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) { + errno = EINVAL; + return (-1); + } + + *flagset_p = &entry_d->ae_flags; + + return (0); +} + +int +acl_set_flagset_np(acl_entry_t entry_d, acl_flagset_t flagset_d) +{ + + if (entry_d == NULL) { + errno = EINVAL; + return (-1); + } + + if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) { + errno = EINVAL; + return (-1); + } + + _entry_brand_as(entry_d, ACL_BRAND_NFS4); + + if (_flag_is_invalid(*flagset_d)) + return (-1); + + entry_d->ae_flags = *flagset_d; + + return (0); +} diff -urNp current/lib/libc/posix1e/acl_from_text.c nfs4acl/lib/libc/posix1e/acl_from_text.c --- current/lib/libc/posix1e/acl_from_text.c 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_from_text.c 2009-04-29 09:35:23.000000000 +0200 @@ -40,45 +40,15 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include #include +#include #include "acl_support.h" static int _posix1e_acl_name_to_id(acl_tag_t tag, char *name, uid_t *id); static acl_tag_t acl_string_to_tag(char *tag, char *qualifier); -static char *string_skip_whitespace(char *string); -static void string_trim_trailing_whitespace(char *string); -static char * -string_skip_whitespace(char *string) -{ - - while (*string && ((*string == ' ') || (*string == '\t'))) { - string++; - } - return (string); -} - -static void -string_trim_trailing_whitespace(char *string) -{ - char *end; - - if (*string == '\0') - return; - - end = string + strlen(string) - 1; - - while (end != string) { - if ((*end == ' ') || (*end == '\t')) { - *end = '\0'; - end--; - } else { - return; - } - } - - return; -} +int _nfs4_acl_entry_from_text(acl_t aclp, char *entry); +int _text_could_be_nfs4_acl(const char *entry); static acl_tag_t acl_string_to_tag(char *tag, char *qualifier) @@ -109,6 +79,112 @@ acl_string_to_tag(char *tag, char *quali } } +static int +_posix1e_acl_entry_from_text(acl_t aclp, char *entry) +{ + acl_tag_t t; + acl_perm_t p; + char *tag, *qualifier, *permission; + uid_t id; + int error; + + assert(_acl_brand(aclp) == ACL_BRAND_POSIX); + + /* Split into three ':' delimited fields. */ + tag = strsep(&entry, ":"); + if (tag == NULL) { + errno = EINVAL; + return (-1); + } + tag = string_skip_whitespace(tag); + if ((*tag == '\0') && (!entry)) { + /* + * Is an entirely comment line, skip to next + * comma. + */ + return (0); + } + string_trim_trailing_whitespace(tag); + + qualifier = strsep(&entry, ":"); + if (qualifier == NULL) { + errno = EINVAL; + return (-1); + } + qualifier = string_skip_whitespace(qualifier); + string_trim_trailing_whitespace(qualifier); + + permission = strsep(&entry, ":"); + if (permission == NULL || entry) { + errno = EINVAL; + return (-1); + } + permission = string_skip_whitespace(permission); + string_trim_trailing_whitespace(permission); + + t = acl_string_to_tag(tag, qualifier); + if (t == -1) { + errno = EINVAL; + return (-1); + } + + error = _posix1e_acl_string_to_perm(permission, &p); + if (error == -1) { + errno = EINVAL; + return (-1); + } + + switch(t) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + if (*qualifier != '\0') { + errno = EINVAL; + return (-1); + } + id = 0; + break; + + case ACL_USER: + case ACL_GROUP: + error = _posix1e_acl_name_to_id(t, qualifier, + &id); + if (error == -1) + return (-1); + break; + + default: + errno = EINVAL; + return (-1); + } + + error = _posix1e_acl_add_entry(aclp, t, id, p); + if (error == -1) + return (-1); + + return (0); +} + +static int +_text_is_nfs4_entry(const char *entry) +{ + int count = 0; + + assert(strlen(entry) > 0); + + while (*entry != '\0') { + if (*entry == ':' || *entry == '@') + count++; + entry++; + } + + if (count <= 2) + return (0); + + return (1); +} + /* * acl_from_text -- Convert a string into an ACL. * Postpone most validity checking until the end and call acl_valid() to do @@ -117,20 +193,16 @@ acl_string_to_tag(char *tag, char *quali acl_t acl_from_text(const char *buf_p) { - acl_tag_t t; - acl_perm_t p; acl_t acl; char *mybuf_p, *line, *cur, *notcomment, *comment, *entry; - char *tag, *qualifier, *permission; int error; - uid_t id; /* Local copy we can mess up. */ mybuf_p = strdup(buf_p); if (mybuf_p == NULL) return(NULL); - acl = acl_init(3); + acl = acl_init(3); /* XXX: WTF, 3? */ if (acl == NULL) { free(mybuf_p); return(NULL); @@ -145,77 +217,33 @@ acl_from_text(const char *buf_p) /* Inner loop: delimit at ',' boundaries. */ while ((entry = strsep(¬comment, ","))) { - /* Now split into three ':' delimited fields. */ - tag = strsep(&entry, ":"); - if (tag == NULL) { - errno = EINVAL; - goto error_label; - } - tag = string_skip_whitespace(tag); - if ((*tag == '\0') && (!entry)) { - /* - * Is an entirely comment line, skip to next - * comma. - */ - continue; - } - string_trim_trailing_whitespace(tag); - qualifier = strsep(&entry, ":"); - if (qualifier == NULL) { - errno = EINVAL; - goto error_label; - } - qualifier = string_skip_whitespace(qualifier); - string_trim_trailing_whitespace(qualifier); - - permission = strsep(&entry, ":"); - if (permission == NULL || entry) { - errno = EINVAL; - goto error_label; - } - permission = string_skip_whitespace(permission); - string_trim_trailing_whitespace(permission); + /* Skip empty lines. */ + if (strlen(string_skip_whitespace(entry)) == 0) + continue; - t = acl_string_to_tag(tag, qualifier); - if (t == -1) { - errno = EINVAL; - goto error_label; + if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) { + if (_text_is_nfs4_entry(entry)) + _acl_brand_as(acl, ACL_BRAND_NFS4); + else + _acl_brand_as(acl, ACL_BRAND_POSIX); } - error = _posix1e_acl_string_to_perm(permission, &p); - if (error == -1) { - errno = EINVAL; - goto error_label; - } - - switch(t) { - case ACL_USER_OBJ: - case ACL_GROUP_OBJ: - case ACL_MASK: - case ACL_OTHER: - if (*qualifier != '\0') { - errno = EINVAL; - goto error_label; - } - id = 0; + switch (_acl_brand(acl)) { + case ACL_BRAND_NFS4: + error = _nfs4_acl_entry_from_text(acl, entry); break; - case ACL_USER: - case ACL_GROUP: - error = _posix1e_acl_name_to_id(t, qualifier, - &id); - if (error == -1) - goto error_label; + case ACL_BRAND_POSIX: + error = _posix1e_acl_entry_from_text(acl, entry); break; default: - errno = EINVAL; - goto error_label; + error = EINVAL; + break; } - error = _posix1e_acl_add_entry(acl, t, id, p); - if (error == -1) + if (error) goto error_label; } } diff -urNp current/lib/libc/posix1e/acl_from_text_nfs4.c nfs4acl/lib/libc/posix1e/acl_from_text_nfs4.c --- current/lib/libc/posix1e/acl_from_text_nfs4.c 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_from_text_nfs4.c 2009-05-26 11:21:36.000000000 +0200 @@ -0,0 +1,312 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acl_support.h" + +#define MAX_ENTRY_LENGTH 512 + +/* + * Parse the tag field of ACL entry passed as "str". If qualifier + * needs to follow, then the variable referenced by "need_qualifier" + * is set to 1, otherwise it's set to 0. + */ +static int +parse_tag(const char *str, acl_entry_t entry, int *need_qualifier) +{ + + assert(need_qualifier != NULL); + *need_qualifier = 0; + + if (strcmp(str, "owner@") == 0) + return (acl_set_tag_type(entry, ACL_USER_OBJ)); + if (strcmp(str, "group@") == 0) + return (acl_set_tag_type(entry, ACL_GROUP_OBJ)); + if (strcmp(str, "everyone@") == 0) + return (acl_set_tag_type(entry, ACL_EVERYONE)); + + *need_qualifier = 1; + + if (strcmp(str, "user") == 0 || strcmp(str, "u") == 0) + return (acl_set_tag_type(entry, ACL_USER)); + if (strcmp(str, "group") == 0 || strcmp(str, "g") == 0) + return (acl_set_tag_type(entry, ACL_GROUP)); + + warnx("malformed ACL: invalid \"tag\" field"); + + return (-1); +} + +/* + * Parse the qualifier field of ACL entry passed as "str". + * If user or group name cannot be resolved, then the variable + * referenced by "need_qualifier" is set to 1. + */ +static int +parse_qualifier(char *str, acl_entry_t entry, int *need_qualifier) +{ + int qualifier_length, error; + id_t id; + char *end; + struct passwd *pwd; + struct group *grp; + acl_tag_t tag; + + assert(need_qualifier != NULL); + *need_qualifier = 0; + + qualifier_length = strlen(str); + + if (qualifier_length == 0) { + warnx("malformed ACL: empty \"qualifier\" field"); + return (-1); + } + + /* XXX: Can we assume that valid username never begins with a digit? */ + if (isdigit(str[0])) { + id = strtod(str, &end); + + if (end - str != qualifier_length) { + warnx("malformed ACL: trailing characters " + "after numerical id"); + return (-1); + } + + return (acl_set_qualifier(entry, &id)); + } + + error = acl_get_tag_type(entry, &tag); + if (error) + return (error); + + assert(tag == ACL_USER || tag == ACL_GROUP); + + if (tag == ACL_USER) { + /* XXX: Thread-unsafe. */ + pwd = getpwnam(str); + if (pwd == NULL) { + *need_qualifier = 1; + return (0); + } + + return (acl_set_qualifier(entry, &(pwd->pw_uid))); + } + + /* XXX: Thread-unsafe. */ + grp = getgrnam(str); + if (grp == NULL) { + *need_qualifier = 1; + return (0); + } + + return (acl_set_qualifier(entry, &(grp->gr_gid))); +} + +static int +parse_access_mask(char *str, acl_entry_t entry) +{ + int error; + acl_perm_t perm; + + error = _nfs4_parse_access_mask(str, &perm); + if (error) + return (error); + + error = acl_set_permset(entry, &perm); + + return (error); +} + +static int +parse_flags(char *str, acl_entry_t entry) +{ + int error; + acl_flag_t flags; + + error = _nfs4_parse_flags(str, &flags); + if (error) + return (error); + + error = acl_set_flagset_np(entry, &flags); + + return (error); +} + +static int +parse_entry_type(const char *str, acl_entry_t entry) +{ + + if (strcmp(str, "allow") == 0) + return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALLOW)); + if (strcmp(str, "deny") == 0) + return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_DENY)); + if (strcmp(str, "audit") == 0) + return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_AUDIT)); + if (strcmp(str, "alarm") == 0) + return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALARM)); + + warnx("malformed ACL: invalid \"type\" field"); + + return (-1); +} + +static int +parse_appended_id(char *str, acl_entry_t entry) +{ + int qualifier_length; + char *end; + id_t id; + + qualifier_length = strlen(str); + if (qualifier_length == 0) { + warnx("malformed ACL: \"appended id\" field present, " + "but empty"); + return (-1); + } + + id = strtod(str, &end); + if (end - str != qualifier_length) { + warnx("malformed ACL: appended id is not a number"); + return (-1); + } + + return (acl_set_qualifier(entry, &id)); +} + +static int +number_of_colons(const char *str) +{ + int count = 0; + + while (*str != '\0') { + if (*str == ':') + count++; + + str++; + } + + return (count); +} + +int +_nfs4_acl_entry_from_text(acl_t aclp, char *str) +{ + int error, need_qualifier; + acl_entry_t entry; + char *field, *qualifier_field; + + error = acl_create_entry(&aclp, &entry); + if (error) + return (error); + + assert(_entry_brand(entry) == ACL_BRAND_NFS4); + + if (str == NULL) + goto truncated_entry; + field = strsep(&str, ":"); + + field = string_skip_whitespace(field); + if ((*field == '\0') && (!str)) { + /* + * Is an entirely comment line, skip to next + * comma. + */ + return (0); + } + + error = parse_tag(field, entry, &need_qualifier); + if (error) + goto malformed_field; + + if (need_qualifier) { + if (str == NULL) + goto truncated_entry; + qualifier_field = field = strsep(&str, ":"); + error = parse_qualifier(field, entry, &need_qualifier); + if (error) + goto malformed_field; + } + + if (str == NULL) + goto truncated_entry; + field = strsep(&str, ":"); + error = parse_access_mask(field, entry); + if (error) + goto malformed_field; + + if (str == NULL) + goto truncated_entry; + /* Do we have "flags" field? */ + if (number_of_colons(str) > 0) { + field = strsep(&str, ":"); + error = parse_flags(field, entry); + if (error) + goto malformed_field; + } + + if (str == NULL) + goto truncated_entry; + field = strsep(&str, ":"); + error = parse_entry_type(field, entry); + if (error) + goto malformed_field; + + if (need_qualifier) { + if (str == NULL) { + warnx("malformed ACL: unknown user or group name " + "\"%s\"", qualifier_field); + goto truncated_entry; + } + + error = parse_appended_id(str, entry); + if (error) + goto malformed_field; + } + + return (0); + +truncated_entry: +malformed_field: + acl_delete_entry(aclp, entry); + errno = EINVAL; + return (-1); +} diff -urNp current/lib/libc/posix1e/acl_get.3 nfs4acl/lib/libc/posix1e/acl_get.3 --- current/lib/libc/posix1e/acl_get.3 2009-05-23 17:12:25.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_get.3 2009-05-26 17:15:43.000000000 +0200 @@ -99,7 +99,10 @@ argument are: .Bl -column -offset 3n "ACL_TYPE_DEFAULT" .It ACL_TYPE_ACCESS POSIX.1e access ACL .It ACL_TYPE_DEFAULT POSIX.1e default ACL +.It ACL_TYPE_NFS4 NFSv4 ACL .El +.Pp +The ACL returned will be branded accordingly. .Sh IMPLEMENTATION NOTES .Fx Ns 's support for POSIX.1e interfaces and features is still under @@ -146,6 +149,7 @@ The file system does not support ACL ret .Xr acl 3 , .Xr acl_free 3 , .Xr acl_get 3 , +.Xr acl_get_brand_np 3 , .Xr acl_set 3 , .Xr posix1e 3 .Sh STANDARDS diff -urNp current/lib/libc/posix1e/acl_get.c nfs4acl/lib/libc/posix1e/acl_get.c --- current/lib/libc/posix1e/acl_get.c 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_get.c 2009-05-25 19:30:06.000000000 +0200 @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include #include +#include #include "acl_support.h" @@ -69,6 +70,9 @@ acl_get_file(const char *path_p, acl_typ return (NULL); } + aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES; + _acl_brand_from_type(aclp, type); + return (aclp); } @@ -89,26 +93,19 @@ acl_get_link_np(const char *path_p, acl_ return (NULL); } + aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES; + _acl_brand_from_type(aclp, type); + return (aclp); } acl_t acl_get_fd(int fd) { - acl_t aclp; - int error; - - aclp = acl_init(ACL_MAX_ENTRIES); - if (aclp == NULL) - return (NULL); + if (fpathconf(fd, _PC_EXTENDED_SECURITY_NP)) + return (acl_get_fd_np(fd, ACL_TYPE_NFS4)); - error = ___acl_get_fd(fd, ACL_TYPE_ACCESS, &aclp->ats_acl); - if (error) { - acl_free(aclp); - return (NULL); - } - - return (aclp); + return (acl_get_fd_np(fd, ACL_TYPE_ACCESS)); } acl_t @@ -128,6 +125,9 @@ acl_get_fd_np(int fd, acl_type_t type) return (NULL); } + aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES; + _acl_brand_from_type(aclp, type); + return (aclp); } @@ -218,3 +218,22 @@ acl_get_tag_type(acl_entry_t entry_d, ac return (0); } + +int +acl_get_entry_type_np(acl_entry_t entry_d, acl_entry_type_t *entry_type_p) +{ + + if (entry_d == NULL || entry_type_p == NULL) { + errno = EINVAL; + return (-1); + } + + if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) { + errno = EINVAL; + return (-1); + } + + *entry_type_p = entry_d->ae_entry_type; + + return (0); +} diff -urNp current/lib/libc/posix1e/acl_get_brand_np.3 nfs4acl/lib/libc/posix1e/acl_get_brand_np.3 --- current/lib/libc/posix1e/acl_get_brand_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_get_brand_np.3 2009-05-26 17:15:43.000000000 +0200 @@ -0,0 +1,86 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_GET_BRAND_NP 3 +.Os +.Sh NAME +.Nm acl_get_brand_np +.Nd retrieve the ACL brand from an ACL entry +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_get_brand_np "acl_t acl" "int *brand_p" +.Sh DESCRIPTION +The +.Fn acl_get_brand_np +function +is a non-portable call that returns the ACL brand for the ACL +.Fa acl . +Upon successful completion, the location referred to by the argument +.Fa brand_p +will be set to the ACL brand of the ACL +.Fa acl . +.Pp +Branding is an internal mechanism intended to prevent mixing POSIX.1e +and NFSv4 entries by mistake. +It's also used by the libc to determine how to print out the ACL. +The first call to function that is specific for one particular brand - POSIX.1e +or NFSv4 - "brands" the ACL. +After that, calling function specific to another brand will result in error. +.Sh RETURN VALUES +.Rv -std acl_get_brand_np +.Sh ERRORS +The +.Fn acl_get_brand_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa acl +does not point to a valid ACL. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_get_brand_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_get_brand_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_get_entry_type_np.3 nfs4acl/lib/libc/posix1e/acl_get_entry_type_np.3 --- current/lib/libc/posix1e/acl_get_entry_type_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_get_entry_type_np.3 2009-05-26 17:15:43.000000000 +0200 @@ -0,0 +1,80 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_GET_ENTRY_TYPE_NP 3 +.Os +.Sh NAME +.Nm acl_get_entry_type_np +.Nd retrieve the ACL type from an NFSv4 ACL entry +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_get_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t *entry_type_p" +.Sh DESCRIPTION +The +.Fn acl_get_entry_type_np +function +is a non-portable call that returns the ACL type for the NFSv4 ACL entry +.Fa entry_d . +Upon successful completion, the location referred to by the argument +.Fa entry_type_p +will be set to the ACL type of the ACL entry +.Fa entry_d . +.Sh RETURN VALUES +.Rv -std acl_get_entry_type_np +.Sh ERRORS +The +.Fn acl_get_entry_type_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa entry_d +is not a valid descriptor for an NFSv4 ACL entry; +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_set_entry_type_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_get_entry_type_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_get_entry_type_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_get_flag_np.3 nfs4acl/lib/libc/posix1e/acl_get_flag_np.3 --- current/lib/libc/posix1e/acl_get_flag_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_get_flag_np.3 2009-05-24 21:07:38.000000000 +0200 @@ -0,0 +1,94 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 10, 2001 +.Dt ACL_GET_FLAG_NP 3 +.Os +.Sh NAME +.Nm acl_get_flag_np +.Nd check if a flag is set in a flagset +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_get_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag" +.Sh DESCRIPTION +The +.Fn acl_get_flag_np +function +is a non-portable function that checks if a flag is set in +a flagset. +.Sh RETURN VALUES +If the flag in +.Fa flag +is set in the flagset +.Fa flagset_d , +a value of +1 +is returned, otherwise a value of +0 +is returned. +.Sh ERRORS +If any of the following conditions occur, the +.Fn acl_get_flag_np +function will return a value of +\-1 +and set global variable +.Va errno +to the corresponding value: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa flag +does not contain a valid ACL flag or argument +.Fa flagset_d +is not a valid ACL flagset. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_add_flag_np 3 , +.Xr acl_clear_flags_np 3 , +.Xr acl_delete_flag_np 3 , +.Xr acl_get_flagset_np 3 , +.Xr acl_set_flagset_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_get_flag_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_get_flag_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_get_flagset_np.3 nfs4acl/lib/libc/posix1e/acl_get_flagset_np.3 --- current/lib/libc/posix1e/acl_get_flagset_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_get_flagset_np.3 2009-05-26 17:15:43.000000000 +0200 @@ -0,0 +1,83 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_GET_FLAGSET_NP 3 +.Os +.Sh NAME +.Nm acl_get_flagset_np +.Nd retrieve flagset from an NFSv4 ACL entry +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_get_flagset_np "acl_entry_t entry_d" "acl_flagset_t *flagset_p" +.Sh DESCRIPTION +The +.Fn acl_get_flagset_np +function +is a non-portable call that returns via +.Fa flagset_np_p +a descriptor to the flagset in the ACL entry +.Fa entry_d . +Subsequent operations using the returned flagset operate +on the flagset within the ACL entry. +.Sh RETURN VALUES +.Rv -std acl_get_flagset_np +.Sh ERRORS +The +.Fn acl_get_flagset_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa entry_d +is not a valid descriptor for an ACL entry. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_add_flag_np 3 , +.Xr acl_clear_flags_np 3 , +.Xr acl_delete_flag_np 3 , +.Xr acl_set_flagset_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_get_flagset_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_get_flagset_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_init.c nfs4acl/lib/libc/posix1e/acl_init.c --- current/lib/libc/posix1e/acl_init.c 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_init.c 2009-06-09 21:29:12.000000000 +0200 @@ -38,10 +38,22 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include #include +#include + +#include "acl_support.h" + +#ifndef CTASSERT +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1] +#endif + +CTASSERT(1 << _ACL_T_ALIGNMENT_BITS > sizeof(struct acl_t_struct)); acl_t acl_init(int count) { + int error; acl_t acl; if (count > ACL_MAX_ENTRIES) { @@ -53,11 +65,14 @@ acl_init(int count) return (NULL); } - acl = malloc(sizeof(struct acl_t_struct)); - if (acl != NULL) { - bzero(acl, sizeof(struct acl_t_struct)); - acl->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES; - } + error = posix_memalign((void *)&acl, 1 << _ACL_T_ALIGNMENT_BITS, + sizeof(struct acl_t_struct)); + if (error) + return (NULL); + + bzero(acl, sizeof(struct acl_t_struct)); + acl->ats_brand = ACL_BRAND_UNKNOWN; + acl->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES; return (acl); } diff -urNp current/lib/libc/posix1e/acl_is_trivial_np.3 nfs4acl/lib/libc/posix1e/acl_is_trivial_np.3 --- current/lib/libc/posix1e/acl_is_trivial_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_is_trivial_np.3 2009-05-26 17:15:43.000000000 +0200 @@ -0,0 +1,84 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" This software was developed by Robert Watson for the TrustedBSD Project. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 28, 2000 +.Dt ACL_STRIP_NP 3 +.Os +.Sh NAME +.Nm acl_is_trivial_np +.Nd determine whether ACL is trivial +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_is_trivial_np "const acl_t aclp" "int *trivialp" +.Sh DESCRIPTION +The +.Fn acl_is_trivial +function determines whether the ACL pointed to by the argument +.Va acl +is trivial. +Upon successful completion, the location referred to by the argument +.Fa trivialp +will be set to 1, if the ACL +.Fa aclp +points to is trivial, or 0 if it's not. +.Pp +ACL is trivial if it can be fully expressed as a file mode without loosing +any access rules. +For POSIX.1e ACLs, ACL is trivial if it has the three required entries, +one for owner, one for owning group, and one for other. +For NFSv4 ACLs, ACL is trivial if it has the "canonical six" entries. +Files that have non-trivial ACL have a plus sign appended after mode bits +in "ls -l" output. +.Sh RETURN VALUES +.Rv -std acl_get_tag_type +.Sh SEE ALSO +.Xr acl 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +Discussion +of the draft continues on the cross-platform POSIX.1e implementation +mailing list. +To join this list, see the +.Fx +POSIX.1e implementation +page for more information. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_is_trivial_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_set.3 nfs4acl/lib/libc/posix1e/acl_set.3 --- current/lib/libc/posix1e/acl_set.3 2009-05-23 17:12:25.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_set.3 2009-05-26 17:15:43.000000000 +0200 @@ -83,7 +83,13 @@ argument are: .Bl -column -offset 3n "ACL_TYPE_DEFAULT" .It ACL_TYPE_ACCESS POSIX.1e access ACL .It ACL_TYPE_DEFAULT POSIX.1e default ACL +.It ACL_TYPE_NFS4 NFSv4 ACL .El +.Pp +Trying to set ACL_TYPE_NFS4 with +.Va acl +branded as POSIX.1e, or ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT with ACL +branded as NFSv4, will result in error. .Sh IMPLEMENTATION NOTES .Fx Ns 's support for POSIX.1e interfaces and features is still under @@ -109,7 +115,7 @@ Argument does not point to a valid ACL for this object, or the ACL type specified in .Va type -is invalid for this object, or both. +is invalid for this object, or there is branding mismatch. .It Bq Er ENAMETOOLONG A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. @@ -132,6 +138,7 @@ read-only. .Xr acl 3 , .Xr acl_delete 3 , .Xr acl_get 3 , +.Xr acl_get_brand_np 3 , .Xr acl_valid 3 , .Xr posix1e 3 .Sh STANDARDS diff -urNp current/lib/libc/posix1e/acl_set.c nfs4acl/lib/libc/posix1e/acl_set.c --- current/lib/libc/posix1e/acl_set.c 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_set.c 2009-05-25 19:30:06.000000000 +0200 @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include #include +#include #include "acl_support.h" @@ -59,6 +60,10 @@ acl_set_file(const char *path_p, acl_typ return (-1); } type = _acl_type_unold(type); + if (_acl_type_not_valid_for_acl(acl, type)) { + errno = EINVAL; + return (-1); + } if (_posix1e_acl(acl, type)) { error = _posix1e_acl_sort(acl); if (error) { @@ -82,6 +87,10 @@ acl_set_link_np(const char *path_p, acl_ return (-1); } type = _acl_type_unold(type); + if (_acl_type_not_valid_for_acl(acl, type)) { + errno = EINVAL; + return (-1); + } if (_posix1e_acl(acl, type)) { error = _posix1e_acl_sort(acl); if (error) { @@ -98,17 +107,11 @@ acl_set_link_np(const char *path_p, acl_ int acl_set_fd(int fd, acl_t acl) { - int error; - error = _posix1e_acl_sort(acl); - if (error) { - errno = error; - return(-1); - } - - acl->ats_cur_entry = 0; + if (fpathconf(fd, _PC_EXTENDED_SECURITY_NP)) + return (acl_set_fd_np(fd, acl, ACL_TYPE_NFS4)); - return (___acl_set_fd(fd, ACL_TYPE_ACCESS, &acl->ats_acl)); + return (acl_set_fd_np(fd, acl, ACL_TYPE_ACCESS)); } int @@ -116,7 +119,15 @@ acl_set_fd_np(int fd, acl_t acl, acl_typ { int error; + if (acl == NULL) { + errno = EINVAL; + return (-1); + } type = _acl_type_unold(type); + if (_acl_type_not_valid_for_acl(acl, type)) { + errno = EINVAL; + return (-1); + } if (_posix1e_acl(acl, type)) { error = _posix1e_acl_sort(acl); if (error) { @@ -143,6 +154,18 @@ acl_set_permset(acl_entry_t entry_d, acl return (-1); } + if ((*permset_d & ACL_POSIX1E_BITS) != *permset_d) { + if ((*permset_d & ACL_NFS4_PERM_BITS) != *permset_d) { + errno = EINVAL; + return (-1); + } + if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) { + errno = EINVAL; + return (-1); + } + _entry_brand_as(entry_d, ACL_BRAND_NFS4); + } + entry_d->ae_perm = *permset_d; return (0); @@ -155,11 +178,11 @@ acl_set_permset(acl_entry_t entry_d, acl int acl_set_qualifier(acl_entry_t entry_d, const void *tag_qualifier_p) { + if (!entry_d || !tag_qualifier_p) { errno = EINVAL; return (-1); } - switch(entry_d->ae_tag) { case ACL_USER: case ACL_GROUP: @@ -187,12 +210,31 @@ acl_set_tag_type(acl_entry_t entry_d, ac } switch(tag_type) { + case ACL_OTHER: + case ACL_MASK: + if (!_entry_brand_may_be(entry_d, ACL_BRAND_POSIX)) { + errno = EINVAL; + return (-1); + } + _entry_brand_as(entry_d, ACL_BRAND_POSIX); + break; + case ACL_EVERYONE: + if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) { + errno = EINVAL; + return (-1); + } + _entry_brand_as(entry_d, ACL_BRAND_NFS4); + break; + } + + switch(tag_type) { case ACL_USER_OBJ: case ACL_USER: case ACL_GROUP_OBJ: case ACL_GROUP: case ACL_MASK: case ACL_OTHER: + case ACL_EVERYONE: entry_d->ae_tag = tag_type; return (0); } @@ -200,3 +242,30 @@ acl_set_tag_type(acl_entry_t entry_d, ac errno = EINVAL; return (-1); } + +int +acl_set_entry_type_np(acl_entry_t entry_d, acl_entry_type_t entry_type) +{ + + if (entry_d == NULL) { + errno = EINVAL; + return (-1); + } + if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) { + errno = EINVAL; + return (-1); + } + _entry_brand_as(entry_d, ACL_BRAND_NFS4); + + switch (entry_type) { + case ACL_ENTRY_TYPE_ALLOW: + case ACL_ENTRY_TYPE_DENY: + case ACL_ENTRY_TYPE_AUDIT: + case ACL_ENTRY_TYPE_ALARM: + entry_d->ae_entry_type = entry_type; + return (0); + } + + errno = EINVAL; + return (-1); +} diff -urNp current/lib/libc/posix1e/acl_set_entry_type_np.3 nfs4acl/lib/libc/posix1e/acl_set_entry_type_np.3 --- current/lib/libc/posix1e/acl_set_entry_type_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_set_entry_type_np.3 2009-05-26 17:15:43.000000000 +0200 @@ -0,0 +1,95 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_SET_ENTRY_TYPE_NP 3 +.Os +.Sh NAME +.Nm acl_set_entry_type_np +.Nd set NFSv4 ACL entry type +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_set_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t entry_type" +.Sh DESCRIPTION +The +.Fn acl_set_entry_type_np +function +is a non-portable call that sets the type of the ACL entry +.Fa entry_d +to the value referred to by +.Fa entry_type . +.Pp +Valid values are: +.Pp +.Bl -column -offset 3n "ACL_ENTRY_TYPE_ALLOW" +.It ACL_ENTRY_TYPE_ALLOW "allow" type entry +.It ACL_ENTRY_TYPE_DENY "deny" type entry +.El +.Pp +This call brands the ACL as NFSv4. +.Sh RETURN VALUES +.Rv -std acl_set_entry_type_np +.Sh ERRORS +The +.Fn acl_set_entry_type_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa entry_d +is not a valid descriptor for an ACL entry. +The value pointed to by +.Fa entry_type +is not valid. +ACL is already branded as POSIX.1e. +.It Bq Er ENOMEM +The value to be returned requires more memory than is allowed +by the hardware or system-imposed memory management constraints. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_get_brand_np 3 , +.Xr acl_get_entry_type_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_get_entry_type_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_get_entry_type_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_set_flagset_np.3 nfs4acl/lib/libc/posix1e/acl_set_flagset_np.3 --- current/lib/libc/posix1e/acl_set_flagset_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_set_flagset_np.3 2009-05-26 17:15:43.000000000 +0200 @@ -0,0 +1,85 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE +.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +.\" POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd March 10, 2001 +.Dt ACL_SET_FLAGSET_NP 3 +.Os +.Sh NAME +.Nm acl_set_flagset_np +.Nd set the flags of an NFSv4 ACL entry +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft int +.Fn acl_set_flagset_np "acl_entry_t entry_d" "acl_flagset_t flagset_d" +.Sh DESCRIPTION +The +.Fn acl_set_flagset_np +function +is a non-portable call that sets the flags of ACL entry +.Fa entry_d +with the flags contained in +.Fa flagset_d . +.Pp +This call brands the ACL as NFSv4. +.Sh RETURN VALUES +.Rv -std acl_set_flagset_np +.Sh ERRORS +The +.Fn acl_set_flagset_np +function fails if: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Fa entry_d +is not a valid descriptor for an ACL entry. +ACL is already branded as POSIX.1e. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_add_flag_np 3 , +.Xr acl_get_brand_np 3 , +.Xr acl_clear_flags_np 3 , +.Xr acl_delete_flag_np 3 , +.Xr acl_get_flagset_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_set_flagset_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +The +.Fn acl_set_flagset_np +function was written by +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_set_tag_type.3 nfs4acl/lib/libc/posix1e/acl_set_tag_type.3 --- current/lib/libc/posix1e/acl_set_tag_type.3 2009-05-23 17:12:25.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_set_tag_type.3 2009-05-26 17:15:43.000000000 +0200 @@ -49,7 +49,7 @@ to the value of .Pp Valid values are: .Pp -.Bl -column -offset 3n "ACL_EVERYONE" +.Bl -column -offset 3n "ACL_OTHER_OBJ" .It ACL_USER_OBJ Permissions apply to file owner .It ACL_USER Permissions apply to additional user specified by qualifier .It ACL_GROUP_OBJ Permissions apply to file group @@ -57,7 +57,15 @@ Valid values are: .It ACL_MASK Permissions specify mask .It ACL_OTHER Permissions apply to "other" .It ACL_OTHER_OBJ Same as ACL_OTHER +.It ACL_EVERYONE Permissions apply to "everyone@" .El +.Pp +Calling +.Fn acl_set_tag_type +with +.Fa tag_type +equal to ACL_MASK, ACL_OTHER or ACL_OTHER_OBJ brands the ACL as POSIX.1e. +Calling it with ACL_EVERYONE brands the ACL as NFSv4. .Sh RETURN VALUES .Rv -std acl_set_tag_type .Sh ERRORS @@ -72,9 +80,11 @@ is not a valid descriptor for an ACL ent Argument .Fa tag_type is not a valid ACL tag type. +ACL is already branded differently. .El .Sh SEE ALSO .Xr acl 3 , +.Xr acl_get_brand_np 3 , .Xr acl_get_tag_type 3 , .Xr posix1e 3 .Sh STANDARDS diff -urNp current/lib/libc/posix1e/acl_strip.c nfs4acl/lib/libc/posix1e/acl_strip.c --- current/lib/libc/posix1e/acl_strip.c 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_strip.c 2009-05-25 19:30:06.000000000 +0200 @@ -0,0 +1,200 @@ +/*- + * Copyright (c) 2001 Chris D. Faulhaber + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR THE VOICES IN HIS HEAD BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include "acl_support.h" + +/* + * These two routines from sys/kern/subr_acl_nfs4.c are used by both kernel + * and libc. + */ +void acl_nfs4_sync_acl_from_mode(struct acl *aclp, mode_t mode, + int file_owner_id); +void acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp); + +static acl_t +_nfs4_acl_strip_np(const acl_t aclp, int recalculate_mask) +{ + acl_t newacl; + mode_t mode; + + newacl = acl_init(ACL_MAX_ENTRIES); + if (newacl == NULL) { + errno = ENOMEM; + return (NULL); + } + + _acl_brand_as(newacl, ACL_BRAND_NFS4); + + acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl)); + acl_nfs4_sync_acl_from_mode(&(newacl->ats_acl), mode, -1); + + return (newacl); +} + +static acl_t +_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask) +{ + acl_t acl_new, acl_old; + acl_entry_t entry, entry_new; + acl_permset_t perm; + acl_tag_t tag; + int entry_id, have_mask_entry; + + assert(_acl_brand(aclp) == ACL_BRAND_POSIX); + + acl_old = acl_dup(aclp); + if (acl_old == NULL) + return (NULL); + + assert(_acl_brand(acl_old) == ACL_BRAND_POSIX); + + have_mask_entry = 0; + acl_new = acl_init(ACL_MAX_ENTRIES); + if (acl_new == NULL) + return (NULL); + tag = ACL_UNDEFINED_TAG; + + /* only save the default user/group/other entries */ + entry_id = ACL_FIRST_ENTRY; + while (acl_get_entry(acl_old, entry_id, &entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + + assert(_entry_brand(entry) == ACL_BRAND_POSIX); + + if (acl_get_tag_type(entry, &tag) == -1) + return (NULL); + + switch(tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_OTHER: + if (acl_get_tag_type(entry, &tag) == -1) + return (NULL); + if (acl_get_permset(entry, &perm) == -1) + return (NULL); + if (acl_create_entry(&acl_new, &entry_new) == -1) + return (NULL); + if (acl_set_tag_type(entry_new, tag) == -1) + return (NULL); + if (acl_set_permset(entry_new, perm) == -1) + return (NULL); + if (acl_copy_entry(entry_new, entry) == -1) + return (NULL); + assert(_entry_brand(entry_new) == ACL_BRAND_POSIX); + break; + case ACL_MASK: + have_mask_entry = 1; + break; + default: + break; + } + } + + assert(_acl_brand(acl_new) == ACL_BRAND_POSIX); + + if (have_mask_entry && recalculate_mask) { + if (acl_calc_mask(&acl_new) == -1) + return (NULL); + } + + return (acl_new); +} + +acl_t +acl_strip_np(const acl_t aclp, int recalculate_mask) +{ + switch (_acl_brand(aclp)) { + case ACL_BRAND_NFS4: + return (_nfs4_acl_strip_np(aclp, recalculate_mask)); + + case ACL_BRAND_POSIX: + return (_posix1e_acl_strip_np(aclp, recalculate_mask)); + + default: + errno = EINVAL; + return (NULL); + } +} + +/* + * Return 1, if ACL is trivial, 0 otherwise. + * + * ACL is trivial, iff its meaning could be fully expressed using just file + * mode. In other words, ACL is trivial iff it doesn't have "+" to the right + * of the mode bits in "ls -l" output ;-) + */ +int +acl_is_trivial_np(const acl_t aclp, int *trivialp) +{ + acl_t tmpacl; + int differs; + + if (aclp == NULL || trivialp == NULL) { + errno = EINVAL; + return (-1); + } + + switch (_acl_brand(aclp)) { + case ACL_BRAND_POSIX: + if (aclp->ats_acl.acl_cnt == 3) + *trivialp = 1; + else + *trivialp = 0; + + return (0); + + case ACL_BRAND_NFS4: + /* + * Calculate trivial ACL - using acl_strip_np - and compare + * with the original. + */ + tmpacl = acl_strip_np(aclp, 0); + if (tmpacl == NULL) + return (-1); + + differs = _acl_differs(aclp, tmpacl); + acl_free(tmpacl); + + if (differs) + *trivialp = 0; + else + *trivialp = 1; + + return (0); + + default: + errno = EINVAL; + return (-1); + } +} diff -urNp current/lib/libc/posix1e/acl_strip_np.3 nfs4acl/lib/libc/posix1e/acl_strip_np.3 --- current/lib/libc/posix1e/acl_strip_np.3 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_strip_np.3 2009-05-24 21:07:38.000000000 +0200 @@ -0,0 +1,109 @@ +.\"- +.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala +.\" All rights reserved. +.\" +.\" This software was developed by Robert Watson for the TrustedBSD Project. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd January 28, 2000 +.Dt ACL_STRIP_NP 3 +.Os +.Sh NAME +.Nm acl_strip_np +.Nd strip exteneded entries from an ACL +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In sys/types.h +.In sys/acl.h +.Ft acl_t +.Fn acl_strip_np "const acl_t acl" "int recalculate_mask" +.Sh DESCRIPTION +The +.Fn acl_strip_np +function returns a pointer to a trivial ACL computed from the ACL pointed +to by the argument +.Va acl . +.Pp +This function may cause memory to be allocated. +The caller should free any +releasable memory, when the new ACL is no longer required, by calling +.Xr acl_free 3 +with the +.Va (void*)acl_t +as an argument. +.Pp +Any existing ACL pointers that refer to the ACL referred to by +.Va acl +shall continue to refer to the ACL. +.Sh RETURN VALUES +Upon successful completion, this function shall return a pointer to the +newly allocated ACL. +Otherwise, a value of +.Va (acl_t)NULL +shall be returned, and +.Va errno +shall be set to indicate the error. +.Sh ERRORS +If any of the following conditions occur, the +.Fn acl_init +function shall return a value of +.Va (acl_t)NULL +and set +.Va errno +to the corresponding value: +.Bl -tag -width Er +.It Bq Er EINVAL +Argument +.Va acl +does not point to a valid ACL. +.It Bq Er ENOMEM +The +.Va acl_t +to be returned requires more memory than is allowed by the hardware or +system-imposed memory management constraints. +.El +.Sh SEE ALSO +.Xr acl 3 , +.Xr acl_is_trivial_np 3 , +.Xr posix1e 3 +.Sh STANDARDS +POSIX.1e is described in IEEE POSIX.1e draft 17. +Discussion +of the draft continues on the cross-platform POSIX.1e implementation +mailing list. +To join this list, see the +.Fx +POSIX.1e implementation +page for more information. +.Sh HISTORY +POSIX.1e support was introduced in +.Fx 4.0 . +The +.Fn acl_strip_np +function was added in +.Fx 8.0 . +.Sh AUTHORS +.An Edward Tomasz Napierala Aq trasz@FreeBSD.org . diff -urNp current/lib/libc/posix1e/acl_support.c nfs4acl/lib/libc/posix1e/acl_support.c --- current/lib/libc/posix1e/acl_support.c 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_support.c 2009-05-26 17:15:43.000000000 +0200 @@ -40,6 +40,8 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #include #include #include +#include +#include #include "acl_support.h" @@ -49,6 +51,37 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e #define ACL_STRING_PERM_NONE '-' /* + * Return 0, if both ACLs are identical. + */ +int +_acl_differs(const acl_t a, const acl_t b) +{ + int i; + struct acl_entry *entrya, *entryb; + + assert(_acl_brand(a) == _acl_brand(b)); + assert(_acl_brand(a) != ACL_BRAND_UNKNOWN); + assert(_acl_brand(b) != ACL_BRAND_UNKNOWN); + + if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt) + return (1); + + for (i = 0; i < b->ats_acl.acl_cnt; i++) { + entrya = &(a->ats_acl.acl_entry[i]); + entryb = &(b->ats_acl.acl_entry[i]); + + if (entrya->ae_tag != entryb->ae_tag || + entrya->ae_id != entryb->ae_id || + entrya->ae_perm != entryb->ae_perm || + entrya->ae_entry_type != entryb->ae_entry_type || + entrya->ae_flags != entryb->ae_flags) + return (1); + } + + return (0); +} + +/* * _posix1e_acl_entry_compare -- compare two acl_entry structures to * determine the order they should appear in. Used by _posix1e_acl_sort to * sort ACL entries into the kernel-desired order -- i.e., the order useful @@ -59,6 +92,10 @@ typedef int (*compare)(const void *, con static int _posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b) { + + assert(_entry_brand(a) == ACL_BRAND_POSIX); + assert(_entry_brand(b) == ACL_BRAND_POSIX); + /* * First, sort between tags -- conveniently defined in the correct * order for verification. @@ -116,6 +153,9 @@ int _posix1e_acl(acl_t acl, acl_type_t type) { + if (_acl_brand(acl) != ACL_BRAND_POSIX) + return (0); + return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT)); } @@ -243,7 +283,8 @@ _posix1e_acl_check(acl_t acl) * MAY HAVE SIDE-EFFECTS */ int -_posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf) +_posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf, + int flags) { struct group *g; struct passwd *p; @@ -251,7 +292,10 @@ _posix1e_acl_id_to_name(acl_tag_t tag, u switch(tag) { case ACL_USER: - p = getpwuid(id); + if (flags & ACL_TEXT_NUMERIC_IDS) + p = NULL; + else + p = getpwuid(id); if (!p) i = snprintf(buf, buf_len, "%d", id); else @@ -264,7 +308,10 @@ _posix1e_acl_id_to_name(acl_tag_t tag, u return (0); case ACL_GROUP: - g = getgrgid(id); + if (flags & ACL_TEXT_NUMERIC_IDS) + g = NULL; + else + g = getgrgid(id); if (g == NULL) i = snprintf(buf, buf_len, "%d", id); else @@ -379,21 +426,52 @@ _posix1e_acl_add_entry(acl_t acl, acl_ta /* * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new" - * counterpart. It's neccessary for the old (pre-NFS4 ACLs) binaries + * counterpart. It's neccessary for the old (pre-NFSv4 ACLs) binaries * to work with new libc and kernel. Fixing 'type' for old binaries with * old libc and new kernel is being done by kern/vfs_acl.c:type_unold(). */ int _acl_type_unold(acl_type_t type) { + switch (type) { case ACL_TYPE_ACCESS_OLD: return (ACL_TYPE_ACCESS); - case ACL_TYPE_DEFAULT_OLD: return (ACL_TYPE_DEFAULT); - default: return (type); } } + +char * +string_skip_whitespace(char *string) +{ + + while (*string && ((*string == ' ') || (*string == '\t'))) + string++; + + return (string); +} + +void +string_trim_trailing_whitespace(char *string) +{ + char *end; + + if (*string == '\0') + return; + + end = string + strlen(string) - 1; + + while (end != string) { + if ((*end == ' ') || (*end == '\t')) { + *end = '\0'; + end--; + } else { + return; + } + } + + return; +} diff -urNp current/lib/libc/posix1e/acl_support.h nfs4acl/lib/libc/posix1e/acl_support.h --- current/lib/libc/posix1e/acl_support.h 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_support.h 2009-05-23 08:37:50.000000000 +0200 @@ -33,17 +33,33 @@ #define _ACL_SUPPORT_H #define _POSIX1E_ACL_STRING_PERM_MAXSIZE 3 /* read, write, exec */ +#define _ACL_T_ALIGNMENT_BITS 13 int _acl_type_unold(acl_type_t type); +int _acl_differs(const acl_t a, const acl_t b); +int _acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type); +void _acl_brand_from_type(acl_t acl, acl_type_t type); +int _acl_brand(const acl_t acl); +int _entry_brand(const acl_entry_t entry); +int _acl_brand_may_be(const acl_t acl, int brand); +int _entry_brand_may_be(const acl_entry_t entry, int brand); +void _acl_brand_as(acl_t acl, int brand); +void _entry_brand_as(const acl_entry_t entry, int brand); +int _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose); +int _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose); +int _nfs4_parse_flags(const char *str, acl_flag_t *var); +int _nfs4_parse_access_mask(const char *str, acl_perm_t *var); int _posix1e_acl_check(acl_t acl); int _posix1e_acl_sort(acl_t acl); int _posix1e_acl(acl_t acl, acl_type_t type); int _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, - char *buf); + char *buf, int flags); int _posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len, char *buf); int _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm); int _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm); +char *string_skip_whitespace(char *string); +void string_trim_trailing_whitespace(char *string); #endif diff -urNp current/lib/libc/posix1e/acl_support_nfs4.c nfs4acl/lib/libc/posix1e/acl_support_nfs4.c --- current/lib/libc/posix1e/acl_support_nfs4.c 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_support_nfs4.c 2009-05-26 11:21:36.000000000 +0200 @@ -0,0 +1,256 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include "acl_support.h" + +struct flagnames_struct { + uint32_t flag; + const char *name; + char letter; +}; + +struct flagnames_struct a_flags[] = + {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'}, + { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'}, + { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'}, + { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'}, + { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'}, + { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'}, + /* + * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it + * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or + * ACE_EVERYONE either, for obvious reasons. + */ + { 0, 0, 0}}; + +struct flagnames_struct a_access_masks[] = + {{ ACL_READ_DATA, "read_data", 'r'}, + { ACL_WRITE_DATA, "write_data", 'w'}, + { ACL_EXECUTE, "execute", 'x'}, + { ACL_APPEND_DATA, "append_data", 'p'}, + { ACL_DELETE_CHILD, "delete_child", 'D'}, + { ACL_DELETE, "delete", 'd'}, + { ACL_READ_ATTRIBUTES, "read_attributes", 'a'}, + { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'}, + { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'}, + { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'}, + { ACL_READ_ACL, "read_acl", 'c'}, + { ACL_WRITE_ACL, "write_acl", 'C'}, + { ACL_WRITE_OWNER, "write_owner", 'o'}, + { ACL_SYNCHRONIZE, "synchronize", 's'}, + { 0, 0, 0}}; + +static const char * +format_flag(uint32_t *var, const struct flagnames_struct *flags) +{ + + for (; flags->name != 0; flags++) { + if ((flags->flag & *var) == 0) + continue; + + *var &= ~flags->flag; + return (flags->name); + } + + return (NULL); +} + +static int +format_flags_verbose(char *str, size_t size, uint32_t var, + const struct flagnames_struct *flags) +{ + size_t off = 0; + const char *tmp; + + while ((tmp = format_flag(&var, flags)) != NULL) { + off += snprintf(str + off, size - off, "%s/", tmp); + assert (off < size); + } + + /* If there were any flags added... */ + if (off > 0) { + off--; + /* ... then remove the last slash. */ + assert(str[off] == '/'); + } + + str[off] = '\0'; + + return (0); +} + +static int +format_flags_compact(char *str, size_t size, uint32_t var, + const struct flagnames_struct *flags) +{ + size_t i; + + for (i = 0; flags[i].name != NULL; i++) { + assert(i < size); + if ((flags[i].flag & var) == 0) + str[i] = '-'; + else + str[i] = flags[i].letter; + } + + str[i] = '\0'; + + return (0); +} + +static int +parse_flags_verbose(const char *strp, uint32_t *var, + const struct flagnames_struct *flags, const char *flags_name, + int *try_compact) +{ + int i, found, ever_found = 0; + char *str, *flag; + + str = strdup(strp); + *try_compact = 0; + *var = 0; + + while (str != NULL) { + flag = strsep(&str, "/:"); + + found = 0; + for (i = 0; flags[i].name != NULL; i++) { + if (strcmp(flags[i].name, flag) == 0) { + *var |= flags[i].flag; + found = 1; + ever_found = 1; + } + } + + if (!found) { + if (ever_found) + warnx("malformed ACL: \"%s\" field contains " + "invalid flag \"%s\"", flags_name, flag); + else + *try_compact = 1; + free(str); + return (-1); + } + } + + free(str); + return (0); +} + +static int +parse_flags_compact(const char *str, uint32_t *var, + const struct flagnames_struct *flags, const char *flags_name) +{ + int i, j, found; + + *var = 0; + + for (i = 0;; i++) { + if (str[i] == '\0') + return (0); + + /* Ignore minus signs. */ + if (str[i] == '-') + continue; + + found = 0; + + for (j = 0; flags[j].name != NULL; j++) { + if (flags[j].letter == str[i]) { + *var |= flags[j].flag; + found = 1; + break; + } + } + + if (!found) { + warnx("malformed ACL: \"%s\" field contains " + "invalid flag \"%c\"", flags_name, str[i]); + return (-1); + } + } +} + +int +_nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose) +{ + + if (verbose) + return (format_flags_verbose(str, size, var, a_flags)); + + return (format_flags_compact(str, size, var, a_flags)); +} + +int +_nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose) +{ + + if (verbose) + return (format_flags_verbose(str, size, var, a_access_masks)); + + return (format_flags_compact(str, size, var, a_access_masks)); +} + +int +_nfs4_parse_flags(const char *str, acl_flag_t *flags) +{ + int error, try_compact; + int tmpflags; + + error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact); + if (error && try_compact) + error = parse_flags_compact(str, &tmpflags, a_flags, "flags"); + + *flags = tmpflags; + + return (error); +} + +int +_nfs4_parse_access_mask(const char *str, acl_perm_t *perms) +{ + int error, try_compact; + int tmpperms; + + error = parse_flags_verbose(str, &tmpperms, a_access_masks, + "access permissions", &try_compact); + if (error && try_compact) + error = parse_flags_compact(str, &tmpperms, + a_access_masks, "access permissions"); + + *perms = tmpperms; + + return (error); +} diff -urNp current/lib/libc/posix1e/acl_to_text.3 nfs4acl/lib/libc/posix1e/acl_to_text.3 --- current/lib/libc/posix1e/acl_to_text.3 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_to_text.3 2009-05-26 17:15:43.000000000 +0200 @@ -31,7 +31,8 @@ .Dt ACL_TO_TEXT 3 .Os .Sh NAME -.Nm acl_to_text +.Nm acl_to_text , +.Nm acl_to_text_np .Nd convert an ACL to text .Sh LIBRARY .Lb libc @@ -40,10 +41,14 @@ .In sys/acl.h .Ft char * .Fn acl_to_text "acl_t acl" "ssize_t *len_p" +.Ft char * +.Fn acl_to_text_np "acl_t acl" "ssize_t *len_p" "int flags" .Sh DESCRIPTION The .Fn acl_to_text -function translates the ACL pointed to by argument +and +.Fn acl_to_text_np +functions translate the ACL pointed to by argument .Va acl into a NULL terminated character string. If the pointer @@ -51,9 +56,22 @@ If the pointer is not NULL, then the function shall return the length of the string (not including the NULL terminator) in the location pointed to by .Va len_p . -The format of the text string returned by +If the ACL is POSIX.1e, the format of the text string returned by .Fn acl_to_text -shall be the POSIX.1e long ACL form. +shall be the POSIX.1e long ACL form. If the ACL is NFSv4, the format +of the text string shall be the compact form, unless the +.Va ACL_TEXT_VERBOSE +flag is given. +.Pp +The flags specified are formed by +.Em or Ns 'ing +the following values +.Pp +.Bl -column -offset 3n "ACL_TEXT_NUMERIC_IDS" +.It ACL_TEXT_VERBOSE Format ACL using verbose form +.It ACL_TEXT_NUMERIC_IDS Do not resolve IDs into user or group names +.It ACL_TEXT_APPEND_ID In addition to user and group names, append numeric IDs +.El .Pp This function allocates any memory necessary to contain the string and returns a pointer to the string. diff -urNp current/lib/libc/posix1e/acl_to_text.c nfs4acl/lib/libc/posix1e/acl_to_text.c --- current/lib/libc/posix1e/acl_to_text.c 2009-04-29 09:27:01.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_to_text.c 2009-05-25 19:30:06.000000000 +0200 @@ -50,8 +50,11 @@ __FBSDID("$FreeBSD: src/lib/libc/posix1e * This function will not produce nice results if it is called with * a non-POSIX.1e semantics ACL. */ -char * -acl_to_text(acl_t acl, ssize_t *len_p) + +char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags); + +static char * +_posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags) { struct acl *acl_int; char *buf, *tmpbuf; @@ -105,7 +108,7 @@ acl_to_text(acl_t acl, ssize_t *len_p) goto error_label; error = _posix1e_acl_id_to_name(ae_tag, ae_id, - UT_NAMESIZE+1, name_buf); + UT_NAMESIZE+1, name_buf, flags); if (error) goto error_label; @@ -165,7 +168,7 @@ acl_to_text(acl_t acl, ssize_t *len_p) goto error_label; error = _posix1e_acl_id_to_name(ae_tag, ae_id, - UT_NAMESIZE+1, name_buf); + UT_NAMESIZE+1, name_buf, flags); if (error) goto error_label; @@ -235,3 +238,25 @@ error_label: if (buf) free(buf); return (NULL); } + +char * +acl_to_text_np(acl_t acl, ssize_t *len_p, int flags) +{ + + switch (_acl_brand(acl)) { + case ACL_BRAND_POSIX: + return (_posix1e_acl_to_text(acl, len_p, flags)); + case ACL_BRAND_NFS4: + return (_nfs4_acl_to_text_np(acl, len_p, flags)); + default: + errno = EINVAL; + return (NULL); + } +} + +char * +acl_to_text(acl_t acl, ssize_t *len_p) +{ + + return (acl_to_text_np(acl, len_p, 0)); +} diff -urNp current/lib/libc/posix1e/acl_to_text_nfs4.c nfs4acl/lib/libc/posix1e/acl_to_text_nfs4.c --- current/lib/libc/posix1e/acl_to_text_nfs4.c 1970-01-01 01:00:00.000000000 +0100 +++ nfs4acl/lib/libc/posix1e/acl_to_text_nfs4.c 2009-05-26 11:21:36.000000000 +0200 @@ -0,0 +1,266 @@ +/*- + * Copyright (c) 2008, 2009 Edward Tomasz Napierała + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "acl_support.h" + +#define MAX_ENTRY_LENGTH 512 + +static int +format_who(char *str, size_t size, const acl_entry_t entry, int numeric) +{ + int error; + acl_tag_t tag; + struct passwd *pwd; + struct group *grp; + id_t *id; + + error = acl_get_tag_type(entry, &tag); + if (error) + return (error); + + switch (tag) { + case ACL_USER_OBJ: + snprintf(str, size, "owner@"); + break; + + case ACL_USER: + id = (id_t *)acl_get_qualifier(entry); + if (id == NULL) + return (-1); + /* XXX: Thread-unsafe. */ + if (!numeric) + pwd = getpwuid(*id); + else + pwd = NULL; + if (pwd == NULL) + snprintf(str, size, "user:%d", (unsigned int)*id); + else + snprintf(str, size, "user:%s", pwd->pw_name); + break; + + case ACL_GROUP_OBJ: + snprintf(str, size, "group@"); + break; + + case ACL_GROUP: + id = (id_t *)acl_get_qualifier(entry); + if (id == NULL) + return (-1); + /* XXX: Thread-unsafe. */ + if (!numeric) + grp = getgrgid(*id); + else + grp = NULL; + if (grp == NULL) + snprintf(str, size, "group:%d", (unsigned int)*id); + else + snprintf(str, size, "group:%s", grp->gr_name); + break; + + case ACL_EVERYONE: + snprintf(str, size, "everyone@"); + break; + + default: + return (-1); + } + + return (0); +} + +static int +format_entry_type(char *str, size_t size, const acl_entry_t entry) +{ + int error; + acl_entry_type_t entry_type; + + error = acl_get_entry_type_np(entry, &entry_type); + if (error) + return (error); + + switch (entry_type) { + case ACL_ENTRY_TYPE_ALLOW: + snprintf(str, size, "allow"); + break; + case ACL_ENTRY_TYPE_DENY: + snprintf(str, size, "deny"); + break; + case ACL_ENTRY_TYPE_AUDIT: + snprintf(str, size, "audit"); + break; + case ACL_ENTRY_TYPE_ALARM: + snprintf(str, size, "alarm"); + break; + default: + return (-1); + } + + return (0); +} + +static int +format_additional_id(char *str, size_t size, const acl_entry_t entry) +{ + int error; + acl_tag_t tag; + id_t *id; + + error = acl_get_tag_type(entry, &tag); + if (error) + return (error); + + switch (tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_EVERYONE: + str[0] = '\0'; + break; + + default: + id = (id_t *)acl_get_qualifier(entry); + if (id == NULL) + return (-1); + snprintf(str, size, ":%d", (unsigned int)*id); + } + + return (0); +} + +static int +format_entry(char *str, size_t size, const acl_entry_t entry, int flags) +{ + size_t off = 0, padding_length, maximum_who_field_length = 18; + acl_permset_t permset; + acl_flagset_t flagset; + int error, len; + char buf[MAX_ENTRY_LENGTH + 1]; + + assert(_entry_brand(entry) == ACL_BRAND_NFS4); + + error = acl_get_flagset_np(entry, &flagset); + if (error) + return (error); + + error = acl_get_permset(entry, &permset); + if (error) + return (error); + + error = format_who(buf, sizeof(buf), entry, + flags & ACL_TEXT_NUMERIC_IDS); + if (error) + return (error); + len = strlen(buf); + padding_length = maximum_who_field_length - len; + if (padding_length > 0) { + memset(str, ' ', padding_length); + off += padding_length; + } + off += snprintf(str + off, size - off, "%s:", buf); + + error = _nfs4_format_access_mask(buf, sizeof(buf), *permset, + flags & ACL_TEXT_VERBOSE); + if (error) + return (error); + off += snprintf(str + off, size - off, "%s:", buf); + + error = _nfs4_format_flags(buf, sizeof(buf), *flagset, + flags & ACL_TEXT_VERBOSE); + if (error) + return (error); + off += snprintf(str + off, size - off, "%s:", buf); + + error = format_entry_type(buf, sizeof(buf), entry); + if (error) + return (error); + off += snprintf(str + off, size - off, "%s", buf); + + if (flags & ACL_TEXT_APPEND_ID) { + error = format_additional_id(buf, sizeof(buf), entry); + if (error) + return (error); + off += snprintf(str + off, size - off, "%s", buf); + } + + off += snprintf(str + off, size - off, "\n"); + + /* Make sure we didn't truncate anything. */ + assert (off < size); + + return (0); +} + +char * +_nfs4_acl_to_text_np(const acl_t aclp, ssize_t *len_p, int flags) +{ + int error, off = 0, size, entry_id = ACL_FIRST_ENTRY; + char *str; + acl_entry_t entry; + + if (aclp->ats_acl.acl_cnt == 0) + return strdup(""); + + size = aclp->ats_acl.acl_cnt * MAX_ENTRY_LENGTH; + str = malloc(size); + if (str == NULL) + return (NULL); + + while (acl_get_entry(aclp, entry_id, &entry) == 1) { + entry_id = ACL_NEXT_ENTRY; + + assert(off < size); + + error = format_entry(str + off, size - off, entry, flags); + if (error) { + errno = EINVAL; + return (NULL); + } + + off = strlen(str); + } + + assert(off < size); + str[off] = '\0'; + + if (len_p != NULL) + *len_p = off; + + return (str); +} diff -urNp current/lib/libc/posix1e/acl_valid.c nfs4acl/lib/libc/posix1e/acl_valid.c --- current/lib/libc/posix1e/acl_valid.c 2009-05-23 07:49:39.000000000 +0200 +++ nfs4acl/lib/libc/posix1e/acl_valid.c 2009-05-23 12:26:06.000000000 +0200 @@ -62,6 +62,10 @@ acl_valid(acl_t acl) errno = EINVAL; return (-1); } + if (!_acl_brand_may_be(acl, ACL_BRAND_POSIX)) { + errno = EINVAL; + return (-1); + } _posix1e_acl_sort(acl); error = _posix1e_acl_check(acl); if (error) { diff -urNp current/sys/sys/acl.h nfs4acl/sys/sys/acl.h --- current/sys/sys/acl.h 2009-05-23 19:03:08.000000000 +0200 +++ nfs4acl/sys/sys/acl.h 2009-05-26 17:15:44.000000000 +0200 @@ -128,8 +128,15 @@ struct acl { struct acl_t_struct { struct acl ats_acl; int ats_cur_entry; - /* Will be used for ACL branding. */ - int ats_spare; + /* + * ats_brand is for libc internal bookkeeping only. + * Applications should use acl_get_brand_np(3). + * Kernel code should use the "type" argument passed + * to VOP_SETACL, VOP_GETACL or VOP_ACLCHECK calls; + * ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT mean POSIX.1e + * ACL, ACL_TYPE_NFS4 means NFSv4 ACL. + */ + int ats_brand; }; typedef struct acl_t_struct *acl_t; @@ -141,6 +148,13 @@ typedef void *acl_t; #endif /* !_KERNEL && !_ACL_PRIVATE */ /* + * Possible valid values for ats_brand field. + */ +#define ACL_BRAND_UNKNOWN 0 +#define ACL_BRAND_POSIX 1 +#define ACL_BRAND_NFS4 2 + +/* * Possible valid values for ae_tag field. For explanation, see acl(9). */ #define ACL_UNDEFINED_TAG 0x00000000 @@ -236,7 +250,12 @@ typedef void *acl_t; */ #define ACL_UNDEFINED_ID ((uid_t)-1) -#ifdef _KERNEL +/* + * Possible values for _flags parameter in acl_to_text_np(3). + */ +#define ACL_TEXT_VERBOSE 0x01 +#define ACL_TEXT_NUMERIC_IDS 0x02 +#define ACL_TEXT_APPEND_ID 0x04 /* * POSIX.1e ACLs are capable of expressing the read, write, and execute bits @@ -247,6 +266,8 @@ typedef void *acl_t; #define ACL_OVERRIDE_MASK (S_IRWXU | S_IRWXG | S_IRWXO) #define ACL_PRESERVE_MASK (~ACL_OVERRIDE_MASK) +#ifdef _KERNEL + /* * Filesystem-independent code to move back and forth between POSIX mode and * POSIX.1e ACL representations. @@ -263,6 +284,17 @@ mode_t acl_posix1e_newfilemode(mode_t struct acl *dacl); struct acl *acl_alloc(int flags); void acl_free(struct acl *aclp); + +void acl_nfs4_sync_acl_from_mode(struct acl *aclp, + mode_t mode, int file_owner_id); +void acl_nfs4_sync_mode_from_acl(mode_t *mode, + const struct acl *aclp); +int acl_nfs4_is_trivial(const struct acl *aclp, + int file_owner_id); +void acl_nfs4_compute_inherited_acl( + const struct acl *parent_aclp, + struct acl *child_aclp, mode_t mode, + int file_owner_id, int is_directory); int acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest); int acl_copy_acl_into_oldacl(const struct acl *source, @@ -272,11 +304,11 @@ int acl_copy_acl_into_oldacl(const str * To allocate 'struct acl', use acl_alloc()/acl_free() instead of this. */ MALLOC_DECLARE(M_ACL); - /* * Filesystem-independent syntax check for a POSIX.1e ACL. */ int acl_posix1e_check(struct acl *acl); +int acl_nfs4_check(const struct acl *aclp, int is_directory); #else /* !_KERNEL */ @@ -312,46 +344,60 @@ __END_DECLS * filesystems (i.e., AFS). */ __BEGIN_DECLS +int acl_add_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag); int acl_add_perm(acl_permset_t _permset_d, acl_perm_t _perm); int acl_calc_mask(acl_t *_acl_p); +int acl_clear_flags_np(acl_flagset_t _flagset_d); int acl_clear_perms(acl_permset_t _permset_d); int acl_copy_entry(acl_entry_t _dest_d, acl_entry_t _src_d); ssize_t acl_copy_ext(void *_buf_p, acl_t _acl, ssize_t _size); acl_t acl_copy_int(const void *_buf_p); int acl_create_entry(acl_t *_acl_p, acl_entry_t *_entry_p); +int acl_create_entry_np(acl_t *_acl_p, acl_entry_t *_entry_p, int _index); int acl_delete_entry(acl_t _acl, acl_entry_t _entry_d); +int acl_delete_entry_np(acl_t _acl, int _index); int acl_delete_fd_np(int _filedes, acl_type_t _type); int acl_delete_file_np(const char *_path_p, acl_type_t _type); int acl_delete_link_np(const char *_path_p, acl_type_t _type); int acl_delete_def_file(const char *_path_p); int acl_delete_def_link_np(const char *_path_p); +int acl_delete_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag); int acl_delete_perm(acl_permset_t _permset_d, acl_perm_t _perm); acl_t acl_dup(acl_t _acl); int acl_free(void *_obj_p); acl_t acl_from_text(const char *_buf_p); +int acl_get_brand_np(acl_t _acl, int *_brand_p); int acl_get_entry(acl_t _acl, int _entry_id, acl_entry_t *_entry_p); acl_t acl_get_fd(int _fd); acl_t acl_get_fd_np(int fd, acl_type_t _type); acl_t acl_get_file(const char *_path_p, acl_type_t _type); +int acl_get_entry_type_np(acl_entry_t _entry_d, acl_entry_type_t *_entry_type_p); acl_t acl_get_link_np(const char *_path_p, acl_type_t _type); void *acl_get_qualifier(acl_entry_t _entry_d); +int acl_get_flag_np(acl_flagset_t _flagset_d, acl_flag_t _flag); int acl_get_perm_np(acl_permset_t _permset_d, acl_perm_t _perm); +int acl_get_flagset_np(acl_entry_t _entry_d, acl_flagset_t *_flagset_p); int acl_get_permset(acl_entry_t _entry_d, acl_permset_t *_permset_p); int acl_get_tag_type(acl_entry_t _entry_d, acl_tag_t *_tag_type_p); acl_t acl_init(int _count); int acl_set_fd(int _fd, acl_t _acl); int acl_set_fd_np(int _fd, acl_t _acl, acl_type_t _type); int acl_set_file(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_set_entry_type_np(acl_entry_t _entry_d, acl_entry_type_t _entry_type); int acl_set_link_np(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_set_flagset_np(acl_entry_t _entry_d, acl_flagset_t _flagset_d); int acl_set_permset(acl_entry_t _entry_d, acl_permset_t _permset_d); int acl_set_qualifier(acl_entry_t _entry_d, const void *_tag_qualifier_p); int acl_set_tag_type(acl_entry_t _entry_d, acl_tag_t _tag_type); ssize_t acl_size(acl_t _acl); char *acl_to_text(acl_t _acl, ssize_t *_len_p); +char *acl_to_text_np(acl_t _acl, ssize_t *_len_p, int _flags); int acl_valid(acl_t _acl); int acl_valid_fd_np(int _fd, acl_type_t _type, acl_t _acl); int acl_valid_file_np(const char *_path_p, acl_type_t _type, acl_t _acl); int acl_valid_link_np(const char *_path_p, acl_type_t _type, acl_t _acl); +int acl_is_trivial_np(const acl_t _acl, int *_trivialp); +acl_t acl_strip_np(const acl_t _acl, int recalculate_mask); __END_DECLS #endif /* !_KERNEL */ diff -urNp current/sys/sys/unistd.h nfs4acl/sys/sys/unistd.h --- current/sys/sys/unistd.h 2009-04-29 09:29:27.000000000 +0200 +++ nfs4acl/sys/sys/unistd.h 2009-04-29 09:37:25.000000000 +0200 @@ -153,6 +153,7 @@ #define _PC_CAP_PRESENT 61 #define _PC_INF_PRESENT 62 #define _PC_MAC_PRESENT 63 +#define _PC_EXTENDED_SECURITY_NP 64 #endif /* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */