FreeBSD/sys/ufs/ufs/ufs_acl.c
/*
 * Set the ACL on a file.
 *
 * As part of the ACL is stored in the inode, and the rest in an EA,
 * this is necessarily non-atomic, and has complex authorization.
 * As ufs_setacl() includes elements of ufs_chown() and ufs_chmod(),
 * a fair number of different access checks may be required to go ahead
 * with the operation at all.
 */
Set the ACL on a file.
As part of the ACL is stored in the inode, and the rest in an EA,
this is necessarily non-atomic, and has complex authorization.
As ufs_setacl() includes elements of ufs_chown() and ufs_chmod(),
a fair number of different access checks may be required to go ahead
with the operation at all.
Set the ACL on a file . As part of the ACL is stored in the inode and the rest in an EA this is necessarily non - atomic and has complex authorization . As ufs_setacl () includes elements of ufs_chown () and ufs_chmod () a fair number of different access checks may be required to go ahead with the operation at all .
static int
ufs_setacl_posix1e(struct vop_setacl_args *ap)
{
	struct inode *ip = VTOI(ap->a_vp);
	int error;
	struct oldacl *old;
	if ((ap->a_vp->v_mount->mnt_flag & MNT_ACLS) == 0)
		return (EINVAL);
	if (ap->a_aclp != NULL) {
		error = VOP_ACLCHECK(ap->a_vp, ap->a_type, ap->a_aclp,
		    ap->a_cred, ap->a_td);
		if (error != 0)
			return (error);
	} else {
		if (ap->a_type != ACL_TYPE_DEFAULT)
			return (EINVAL);
		if (ap->a_vp->v_type != VDIR)
			return (ENOTDIR);
	}
	if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY)
		return (EROFS);
	if (ip->i_flags & (IMMUTABLE | APPEND))
		return (EPERM);
	if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td)))
		return (error);
	switch(ap->a_type) {
	case ACL_TYPE_ACCESS:
		old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO);
		error = acl_copy_acl_into_oldacl(ap->a_aclp, old);
		if (error == 0) {
			error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
			    POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE,
			    POSIX1E_ACL_ACCESS_EXTATTR_NAME, sizeof(*old),
			    (char *) old, ap->a_td);
		}
		free(old, M_ACL);
		break;
	case ACL_TYPE_DEFAULT:
		if (ap->a_aclp == NULL) {
			error = vn_extattr_rm(ap->a_vp, IO_NODELOCKED,
			    POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
			    POSIX1E_ACL_DEFAULT_EXTATTR_NAME, ap->a_td);
			if (error == ENOATTR)
				error = 0;
		} else {
			old = malloc(sizeof(*old), M_ACL, M_WAITOK | M_ZERO);
			error = acl_copy_acl_into_oldacl(ap->a_aclp, old);
			if (error == 0) {
				error = vn_extattr_set(ap->a_vp, IO_NODELOCKED,
				    POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE,
				    POSIX1E_ACL_DEFAULT_EXTATTR_NAME,
				    sizeof(*old), (char *) old, ap->a_td);
			}
			free(old, M_ACL);
		}
		break;
	default:
		error = EINVAL;
	}
	if (error == ENOATTR)
		return (EOPNOTSUPP);
	if (error != 0)
		return (error);
	if (ap->a_type == ACL_TYPE_ACCESS) {
		ufs_sync_inode_from_acl(ap->a_aclp, ip);
		ip->i_flag |= IN_CHANGE;
		error = UFS_UPDATE(ap->a_vp, 0);
	}
	VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB);
	return (error);
}
static int ufs_setacl_posix1e ( struct vop_setacl_args * ap ) { struct inode * ip = VTOI ( ap -> a_vp ) ; int error ; struct oldacl * old ; if ( ( ap -> a_vp -> v_mount -> mnt_flag & MNT_ACLS ) == 0 ) return ( EINVAL ) ; if ( ap -> a_aclp != NULL ) { error = VOP_ACLCHECK ( ap -> a_vp , ap -> a_type , ap -> a_aclp , ap -> a_cred , ap -> a_td ) ; if ( error != 0 ) return ( error ) ; } else { if ( ap -> a_type != ACL_TYPE_DEFAULT ) return ( EINVAL ) ; if ( ap -> a_vp -> v_type != VDIR ) return ( ENOTDIR ) ; } if ( ap -> a_vp -> v_mount -> mnt_flag & MNT_RDONLY ) return ( EROFS ) ; if ( ip -> i_flags & ( IMMUTABLE | APPEND ) ) return ( EPERM ) ; if ( ( error = VOP_ACCESS ( ap -> a_vp , VADMIN , ap -> a_cred , ap -> a_td ) ) ) return ( error ) ; switch ( ap -> a_type ) { case ACL_TYPE_ACCESS : old = malloc ( sizeof ( * old ) , M_ACL , M_WAITOK | M_ZERO ) ; error = acl_copy_acl_into_oldacl ( ap -> a_aclp , old ) ; if ( error == 0 ) { error = vn_extattr_set ( ap -> a_vp , IO_NODELOCKED , POSIX1E_ACL_ACCESS_EXTATTR_NAMESPACE , POSIX1E_ACL_ACCESS_EXTATTR_NAME , sizeof ( * old ) , ( char * ) old , ap -> a_td ) ; } free ( old , M_ACL ) ; break ; case ACL_TYPE_DEFAULT : if ( ap -> a_aclp == NULL ) { error = vn_extattr_rm ( ap -> a_vp , IO_NODELOCKED , POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE , POSIX1E_ACL_DEFAULT_EXTATTR_NAME , ap -> a_td ) ; if ( error == ENOATTR ) error = 0 ; } else { old = malloc ( sizeof ( * old ) , M_ACL , M_WAITOK | M_ZERO ) ; error = acl_copy_acl_into_oldacl ( ap -> a_aclp , old ) ; if ( error == 0 ) { error = vn_extattr_set ( ap -> a_vp , IO_NODELOCKED , POSIX1E_ACL_DEFAULT_EXTATTR_NAMESPACE , POSIX1E_ACL_DEFAULT_EXTATTR_NAME , sizeof ( * old ) , ( char * ) old , ap -> a_td ) ; } free ( old , M_ACL ) ; } break ; default : error = EINVAL ; } if ( error == ENOATTR ) return ( EOPNOTSUPP ) ; if ( error != 0 ) return ( error ) ; if ( ap -> a_type == ACL_TYPE_ACCESS ) { ufs_sync_inode_from_acl ( ap -> a_aclp , ip ) ; ip -> i_flag |= IN_CHANGE ; error = UFS_UPDATE ( ap -> a_vp , 0 ) ; } VN_KNOTE_UNLOCKED ( ap -> a_vp , NOTE_ATTRIB ) ; return ( error ) ; }
Set the ACL on a file.
Set the ACL on a file .
/*
	 * If this is a set operation rather than a delete operation,
	 * invoke VOP_ACLCHECK() on the passed ACL to determine if it is
	 * valid for the target.  This will include a check on ap->a_type.
	 */ /*
		 * Set operation.
		 */ /*
		 * Delete operation.
		 * POSIX.1e allows only deletion of the default ACL on a
		 * directory (ACL_TYPE_DEFAULT).
		 */ /*
	 * Authorize the ACL operation.
	 */ /*
	 * Must hold VADMIN (be file owner) or have appropriate privilege.
	 */ /*
			 * Attempting to delete a non-present default ACL
			 * will return success for portability purposes.
			 * (TRIX)
			 *
			 * XXX: Note that since we can't distinguish
			 * "that EA is not supported" from "that EA is not
			 * defined", the success case here overlaps the
			 * the ENOATTR->EOPNOTSUPP case below.
		 	 */ /*
	 * Map lack of attribute definition in UFS_EXTATTR into lack of
	 * support for ACLs on the filesystem.
	 */ /*
		 * Now that the EA is successfully updated, update the
		 * inode and mark it as changed.
		 */