Date: Sat, 24 May 2008 18:51:12 GMT From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 142223 for review Message-ID: <200805241851.m4OIpCnK076739@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=142223 Change 142223 by trasz@trasz_traszkan on 2008/05/24 18:50:18 - Add SunOS-compatible API for ACL (ace_t) saving and loading. It's only temporary, as having two completely separate APIs for ACLs is not a good idea. - Add saving and restoring of NFSv4 ACLs to UFS. Not well tested yet, and again only temporary, as it stores the number of entries as a separate extattr. Affected files ... .. //depot/projects/soc2008/trasz_nfs4acl/lib/libc/include/namespace.h#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/lib/libc/sys/Symbol.map#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/lib/libc_r/uthread/Makefile.inc#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/lib/libc_r/uthread/uthread_facl.c#1 add .. //depot/projects/soc2008/trasz_nfs4acl/sys/compat/freebsd32/syscalls.master#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/syscalls.master#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_acl.c#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vnode_if.src#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/acl.h#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/mount.h#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/sys/unistd.h#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ffs/ffs_vfsops.c#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/acl.h#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_acl.c#2 edit .. //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_vnops.c#2 edit Differences ... ==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc/include/namespace.h#2 (text+ko) ==== @@ -53,6 +53,8 @@ #define __acl_delete_fd ___acl_delete_fd #define __acl_get_fd ___acl_get_fd #define __acl_set_fd ___acl_set_fd +#define acl _acl +#define facl _facl #define bind _bind #define __cap_get_fd ___cap_get_fd #define __cap_set_fd ___cap_set_fd ==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc/sys/Symbol.map#2 (text) ==== @@ -20,6 +20,8 @@ __acl_set_fd; __acl_set_file; __acl_set_link; + acl; + facl; __getcwd; __mac_execve; __mac_get_fd; ==== //depot/projects/soc2008/trasz_nfs4acl/lib/libc_r/uthread/Makefile.inc#2 (text+ko) ==== @@ -9,6 +9,7 @@ uthread_acl_get_fd.c \ uthread_acl_set_fd.c \ uthread_acl_aclcheck_fd.c \ + uthread_facl.c \ uthread_aio_suspend.c \ uthread_atfork.c \ uthread_attr_destroy.c \ ==== //depot/projects/soc2008/trasz_nfs4acl/sys/compat/freebsd32/syscalls.master#2 (text+ko) ==== @@ -795,6 +795,8 @@ 480 AUE_FTRUNCATE STD { int freebsd32_ftruncate(int fd, \ u_int32_t lengthlo, u_int32_t lengthhi); } 481 AUE_KILL NOPROTO { int thr_kill2(pid_t pid, long id, int sig); } +482 AUE_NULL STD { int acl(char *path, int cmd, int nentries, void *aclp); } +483 AUE_NULL STD { int facl(int filedes, int cmd, int nentries, void *aclp); } 482 AUE_SHMOPEN NOPROTO { int shm_open(const char *path, int flags, \ mode_t mode); } 483 AUE_SHMUNLINK NOPROTO { int shm_unlink(const char *path); } ==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/syscalls.master#2 (text+ko) ==== @@ -843,6 +843,8 @@ 479 AUE_TRUNCATE STD { int truncate(char *path, off_t length); } 480 AUE_FTRUNCATE STD { int ftruncate(int fd, off_t length); } 481 AUE_KILL STD { int thr_kill2(pid_t pid, long id, int sig); } +482 AUE_NULL STD { int acl(char *path, int cmd, int nentries, void *aclp); } +483 AUE_NULL STD { int facl(int filedes, int cmd, int nentries, void *aclp); } 482 AUE_SHMOPEN STD { int shm_open(const char *path, int flags, \ mode_t mode); } 483 AUE_SHMUNLINK STD { int shm_unlink(const char *path); } ==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vfs_acl.c#2 (text+ko) ==== @@ -66,6 +66,8 @@ static int vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type, struct acl *aclp); +MALLOC_DEFINE(M_ACE, "acebuffers", "NFSv4 ACL buffers"); + /* * These calls wrap the real vnode operations, and are called by the syscall * code once the syscall has converted the path or file descriptor to a vnode @@ -420,6 +422,157 @@ return (error); } +static int +kacl_get(struct thread *td, struct vnode *vp, int nentries, void *aclp) +{ + void *inkernelacl; + int error, count; + + if (nentries <= 0 || nentries > MAX_ACL_ENTRIES) + return (EINVAL); + + inkernelacl = malloc(nentries * sizeof(ace_t), M_ACE, M_ZERO | M_WAITOK); + KASSERT(inkernelacl != NULL, "null inkernelacl"); + + VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#if 0 + error = mac_check_vnode_getacl(td->td_ucred, vp, ACL_TYPE_NFS4); + if (error != 0) + goto out; +#endif + error = VOP_GETACE(vp, nentries, &count, inkernelacl, td->td_ucred, td); +#ifdef MAC +out: +#endif + VOP_UNLOCK(vp, 0, td); + + if (error == 0) { + td->td_retval[0] = count; + error = copyout(inkernelacl, aclp, nentries * sizeof(ace_t)); + } + + free(inkernelacl, M_ACE); + + return (error); +} + +static int +kacl_getaclcnt(struct thread *td, struct vnode *vp, int nentries, void *notused) +{ + int error, count; + + VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#if 0 + error = mac_check_vnode_getacl(td->td_ucred, vp, ACL_TYPE_NFS4); + if (error != 0) + goto out; +#endif + error = VOP_GETACECNT(vp, &count, td->td_ucred, td); +#ifdef MAC +out: +#endif + VOP_UNLOCK(vp, 0, td); + + if (error == 0) + td->td_retval[0] = count; + + return (error); +} + +static int +kacl_set(struct thread *td, struct vnode *vp, int nentries, void *aclp) +{ + struct mount *mp; + void *inkernelacl; + int error; + + if (nentries <= 0 || nentries > MAX_ACL_ENTRIES) + return (EINVAL); + + inkernelacl = malloc(nentries * sizeof(ace_t), M_ACE, M_ZERO | M_WAITOK); + KASSERT(inkernelacl != NULL, "null inkernelacl"); + + error = copyin(aclp, inkernelacl, nentries * sizeof(ace_t)); + if (error) + goto out_free; + + error = vn_start_write(vp, &mp, V_WAIT | PCATCH); + if (error != 0) + goto out_free; + + VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); +#if 0 + error = mac_check_vnode_setacl(td->td_ucred, vp, type, &inkernelacl); + if (error != 0) + goto out; +#endif + error = VOP_SETACE(vp, nentries, inkernelacl, td->td_ucred, td); +#ifdef MAC +out: +#endif + VOP_UNLOCK(vp, 0, td); + vn_finished_write(mp); + +out_free: + free(inkernelacl, M_ACE); + + return (error); +} + +static int +kacl(struct thread *td, struct vnode *vp, int cmd, int nentries, void *aclp) +{ + switch (cmd) { + case ACE_GETACL: + return (kacl_get(td, vp, nentries, aclp)); + + case ACE_GETACLCNT: + return (kacl_getaclcnt(td, vp, nentries, aclp)); + + case ACE_SETACL: + return (kacl_set(td, vp, nentries, aclp)); + + default: + return (EINVAL); + } +} + +int +acl(struct thread *td, struct acl_args *uap) +{ + struct nameidata nd; + int vfslocked, error; + + NDINIT(&nd, LOOKUP, MPSAFE|FOLLOW, UIO_USERSPACE, uap->path, td); + error = namei(&nd); + vfslocked = NDHASGIANT(&nd); + if (error == 0) { + error = kacl(td, nd.ni_vp, uap->cmd, uap->nentries, uap->aclp); + NDFREE(&nd, 0); + } + VFS_UNLOCK_GIANT(vfslocked); + return (error); +} + +int +facl(struct thread *td, struct facl_args *uap) +{ + struct file *fp; + int vfslocked, error; + + error = getvnode(td->td_proc->p_fd, uap->filedes, &fp); + if (error == 0) { + vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount); + error = kacl(td, fp->f_vnode, uap->cmd, uap->nentries, uap->aclp); + fdrop(fp, td); + VFS_UNLOCK_GIANT(vfslocked); + } + return (error); +} + /* ARGUSED */ static void ==== //depot/projects/soc2008/trasz_nfs4acl/sys/kern/vnode_if.src#2 (text+ko) ==== @@ -513,6 +513,35 @@ IN struct thread *td; }; +%% getace vp L L L + +vop_getace { + IN struct vnode *vp; + IN int nentries; + OUT int *count; + OUT void *aclp; + IN struct ucred *cred; + IN struct thread *td; +}; + +%% getacecnt vp L L L + +vop_getacecnt { + IN struct vnode *vp; + OUT int *count; + IN struct ucred *cred; + IN struct thread *td; +}; + +%% setace vp E E E + +vop_setace { + IN struct vnode *vp; + IN int nentries; + IN void *aclp; + IN struct ucred *cred; + IN struct thread *td; +}; %% closeextattr vp L L L ==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/acl.h#2 (text+ko) ==== @@ -113,9 +113,90 @@ */ #define ACL_UNDEFINED_ID ((uid_t)-1) +/* + * NFSv4 ACL types and related constants. + */ +#ifndef _SOLARIS_C_SOURCE /* XXX: Otherwise zfs won't compile. */ + +#define NFS4_ACL_EXTATTR_NAMESPACE EXTATTR_NAMESPACE_SYSTEM +#define NFS4_ACL_EXTATTR_NAME "nfs4.acl" +#define NFS4_ACLCNT_EXTATTR_NAME "nfs4.aclcount" + +#define MAX_ACL_ENTRIES 1024 + +typedef uint32_t ace_type_t; +typedef uint32_t ace_flags_t; +typedef uint32_t ace_mask_t; + +struct ace_t_struct { + ace_type_t a_type; + ace_flags_t a_flags; + ace_mask_t a_access_mask; + uid_t a_who; +}; +typedef struct ace_t_struct ace_t; + +/* + * Possible values for a_type field. + */ +#define ACE_ACCESS_ALLOWED_ACE_TYPE 0x00000000 +#define ACE_ACCESS_DENIED_ACE_TYPE 0x00000001 +#define ACE_SYSTEM_AUDIT_ACE_TYPE 0x00000002 +#define ACE_SYSTEM_ALARM_ACE_TYPE 0x00000003 +/* + * Possible values for a_flags field. + */ +#define ACE_FILE_INHERIT_ACE 0x00000001 +#define ACE_DIRECTORY_INHERIT_ACE 0x00000002 +#define ACE_NO_PROPAGATE_INHERIT_ACE 0x00000004 +#define ACE_INHERIT_ONLY_ACE 0x00000008 +#define ACE_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010 +#define ACE_FAILED_ACCESS_ACE_FLAG 0x00000020 +#define ACE_IDENTIFIER_GROUP 0x00000040 + +/* + * The following three values go into a_flags field and mean, + * respectively, OWNER@, GROUP@ and EVERYONE@. + */ +#define ACE_OWNER 0x10000000 +#define ACE_GROUP 0x20000000 +#define ACE_EVERYONE 0x40000000 + +/* + * Possible values for a_access_mask field. + */ +#define ACE_READ_DATA 0x00000001 +#define ACE_LIST_DIRECTORY 0x00000001 +#define ACE_WRITE_DATA 0x00000002 +#define ACE_ADD_FILE 0x00000002 +#define ACE_APPEND_DATA 0x00000004 +#define ACE_ACE_ADD_SUBDIRECTORY 0x00000004 +#define ACE_READ_NAMED_ATTRS 0x00000008 +#define ACE_WRITE_NAMED_ATTRS 0x00000010 +#define ACE_EXECUTE 0x00000020 +#define ACE_DELETE_CHILD 0x00000040 +#define ACE_READ_ATTRIBUTES 0x00000080 +#define ACE_WRITE_ATTRIBUTES 0x00000100 +#define ACE_DELETE 0x00010000 +#define ACE_READ_ACL 0x00020000 +#define ACE_WRITE_ACL 0x00040000 +#define ACE_WRITE_OWNER 0x00080000 +#define ACE_SYNCHRONIZE 0x00100000 + +/* + * Possible values for _cmd parameter for acl(2)/facl(2). + */ +#define ACE_SETACL 1 +#define ACE_GETACL 2 +#define ACE_GETACLCNT 3 + +#endif /* !_SOLARIS_C_SOURCE */ + #ifdef _KERNEL +MALLOC_DECLARE(M_ACE); + extern uma_zone_t acl_zone; /* @@ -151,7 +232,7 @@ /* * Syscall interface -- use the library calls instead as the syscalls have - * strict acl entry ordering requirements. + * strict acl entry ordering requirements. This does not support NFSv4 ACLs. */ __BEGIN_DECLS int __acl_aclcheck_fd(int _filedes, acl_type_t _type, struct acl *_aclp); @@ -171,6 +252,14 @@ __END_DECLS /* + * SunOS-compatible syscall interface. It supports only NFSv4 ACLs (ace_t). + */ +__BEGIN_DECLS +int acl(char *_path, int _cmd, int _nentries, void *_aclp); +int facl(int _filedes, int _cmd, int _nentries, void *_aclp); +__END_DECLS + +/* * Supported POSIX.1e ACL manipulation and assignment/retrieval API _np calls * are local extensions that reflect an environment capable of opening file * descriptors of directories, and allowing additional ACL type for different ==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/mount.h#2 (text+ko) ==== @@ -233,6 +233,7 @@ #define MNT_NOATIME 0x10000000 /* disable update of file access time */ #define MNT_NOCLUSTERR 0x40000000 /* disable cluster read */ #define MNT_NOCLUSTERW 0x80000000 /* disable cluster write */ +#define MNT_NFS4ACLS 0x00000010 /* * NFS export related mount flags. @@ -268,7 +269,7 @@ MNT_ROOTFS | MNT_NOATIME | MNT_NOCLUSTERR| \ MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \ MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \ - MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS) + MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | MNT_NFS4ACLS) /* Mask of flags that can be updated. */ #define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \ @@ -276,7 +277,7 @@ MNT_NOATIME | \ MNT_NOSYMFOLLOW | MNT_IGNORE | \ MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | \ - MNT_ACLS | MNT_USER) + MNT_ACLS | MNT_USER | MNT_NFS4ACLS) /* * External filesystem command modifier flags. @@ -294,10 +295,6 @@ #define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \ MNT_FORCE | MNT_SNAPSHOT | MNT_BYFSID) /* - * Still available. - */ -#define MNT_SPARE_0x00000010 0x00000010 -/* * Internal filesystem control flags stored in mnt_kern_flag. * * MNTK_UNMOUNT locks the mount entry so that name lookup cannot proceed ==== //depot/projects/soc2008/trasz_nfs4acl/sys/sys/unistd.h#2 (text+ko) ==== @@ -153,6 +153,7 @@ #define _PC_CAP_PRESENT 61 #define _PC_INF_PRESENT 62 #define _PC_MAC_PRESENT 63 +#define _ACL_ACE_ENABLED 64 #endif /* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */ ==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ffs/ffs_vfsops.c#2 (text+ko) ==== @@ -125,7 +125,7 @@ static const char *ffs_opts[] = { "acls", "async", "noatime", "noclusterr", "noclusterw", "noexec", "export", "force", "from", "multilabel", "snapshot", "nosuid", "suiddir", "nosymfollow", "sync", - "union", NULL }; + "union", "nfs4acls", NULL }; static int ffs_mount(struct mount *mp, struct thread *td) @@ -186,6 +186,14 @@ if (vfs_getopt(mp->mnt_optnew, "snapshot", NULL, NULL) == 0) mntorflags |= MNT_SNAPSHOT; + if (vfs_getopt(mp->mnt_optnew, "nfs4acls", NULL, NULL) == 0) { + printf("WARNING: both acls and nfs4acls specified\n"); +#if 0 + return (EINVAL); +#endif + mntorflags |= MNT_NFS4ACLS; + } + MNT_ILOCK(mp); mp->mnt_flag = (mp->mnt_flag | mntorflags) & ~mntandnotflags; MNT_IUNLOCK(mp); @@ -816,7 +824,12 @@ if ((fs->fs_flags & FS_ACLS) != 0) { #ifdef UFS_ACL MNT_ILOCK(mp); - mp->mnt_flag |= MNT_ACLS; + + if (mp->mnt_flag | MNT_NFS4ACLS) + printf("WARNING: ACLs flag on fs conflicts with nfs4acls mount option; flag ignored\n"); + else + mp->mnt_flag |= MNT_ACLS; + MNT_IUNLOCK(mp); #else printf( ==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/acl.h#2 (text+ko) ==== @@ -44,6 +44,13 @@ int ufs_setacl(struct vop_setacl_args *); int ufs_aclcheck(struct vop_aclcheck_args *); +int ufs_load_acecnt(struct vnode *vp, int *nentries, struct thread *td); +int ufs_nfs4acl_from_inode(struct vop_getace_args *ap); +void ufs_sync_inode_from_nfs4acl(ace_t *aclp, int nentries, struct inode *ip); +int ufs_getace(struct vop_getace_args *ap); +int ufs_getacecnt(struct vop_getacecnt_args *ap); +int ufs_setace(struct vop_setace_args *ap); + #endif /* !_KERNEL */ #endif /* !_UFS_UFS_ACL_H_ */ ==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_acl.c#2 (text+ko) ==== @@ -438,4 +438,206 @@ return (acl_posix1e_check(ap->a_aclp)); } +int +ufs_load_acecnt(struct vnode *vp, int *nentries, struct thread *td) +{ + int error, length; + + length = sizeof (*nentries); + + error = vn_extattr_get(vp, IO_NODELOCKED, + NFS4_ACL_EXTATTR_NAMESPACE, + NFS4_ACLCNT_EXTATTR_NAME, &length, + (char *)nentries, td); + + if (error == 0 && length != sizeof (*nentries)) { + printf("ufs_load_acecnt: short read (%d bytes)\n", length); + return (EIO); + } + + if (error != 0 && error != ENOATTR) + printf("ufs_load_acecnt: error %d\n", error); + + return error; +} + +int +ufs_nfs4acl_from_inode(struct vop_getace_args *ap) +{ + if (ap->a_nentries < 6) + return (ENOSPC); + + *(ap->a_count) = 6; + + return (0); +} + +void +ufs_sync_inode_from_nfs4acl(ace_t *aclp, int nentries, struct inode *ip) +{ +} + +int +ufs_getace(struct vop_getace_args *ap) +{ + int error, length, expected_length; + + /* + * XXX: If ufs_getace() should work on file systems not supporting + * ACLs, remove this check. + */ + if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0) + return (EOPNOTSUPP); + + error = ufs_load_acecnt(ap->a_vp, ap->a_count, ap->a_td); + switch (error) { + case ENOATTR: + return (ufs_nfs4acl_from_inode(ap)); + + case 0: + break; + + default: + return (EPERM); + } + + if (*(ap->a_count) > ap->a_nentries) + return (ENOSPC); + + expected_length = *(ap->a_count) * sizeof(ace_t); + length = expected_length; + + error = vn_extattr_get(ap->a_vp, IO_NODELOCKED, + NFS4_ACL_EXTATTR_NAMESPACE, + NFS4_ACL_EXTATTR_NAME, &length, (char *)ap->a_aclp, + ap->a_td); + + switch (error) { + /* XXX: If ufs_getace() should work on filesystems without + * the EA configured, add case EOPNOTSUPP here. */ + case ENOATTR: + /* + * Legitimately no ACL set on object, purely + * emulate it through the inode. These fields will + * be updated when the ACL is synchronized with + * the inode later. + */ + return (ufs_nfs4acl_from_inode(ap)); + + case 0: + if (length != expected_length) { + /* + * A short (or long) read, meaning that for + * some reason the ACL is corrupted. Return + * EPERM since the object DAC protections + * are unsafe. + */ + printf("ufs_getace(): short read, wanted %d bytes, " + "got only %d.", expected_length, length); + + return (EPERM); + } + + break; + + default: + error = EINVAL; + } + + return (error); +} + +int +ufs_getacecnt(struct vop_getacecnt_args *ap) +{ + int error; + + /* + * XXX: If ufs_getacecnt() should work on file systems not supporting + * ACLs, remove this check. + */ + if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0) + return (EOPNOTSUPP); + + error = ufs_load_acecnt(ap->a_vp, ap->a_count, ap->a_td); + + if (error == ENOATTR) { + *(ap->a_count) = 6; + error = 0; + } + + return (error); +} + +int +ufs_setace(struct vop_setace_args *ap) +{ + struct inode *ip = VTOI(ap->a_vp); + int error, nentries; + + if ((ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) == 0) + return (EOPNOTSUPP); + + /* + * XXX: Check if ACL is valid. + */ + + /* + * XXX: Remove ACL if it's trivial. + */ + + if (ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) + return (EROFS); + + /* + * Authorize the ACL operation. + */ + if (ip->i_flags & (IMMUTABLE | APPEND)) + return (EPERM); + + /* + * Must hold VADMIN (be file owner) or have appropriate privilege. + */ + if ((error = VOP_ACCESS(ap->a_vp, VADMIN, ap->a_cred, ap->a_td))) + return (error); + + nentries = ap->a_nentries; + + error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, + NFS4_ACL_EXTATTR_NAMESPACE, + NFS4_ACLCNT_EXTATTR_NAME, sizeof(int), + (char *)&nentries, ap->a_td); + + if (error == ENOATTR) + return (EOPNOTSUPP); + + if (error != 0) + return (error); + + error = vn_extattr_set(ap->a_vp, IO_NODELOCKED, + NFS4_ACL_EXTATTR_NAMESPACE, + NFS4_ACL_EXTATTR_NAME, ap->a_nentries * sizeof(ace_t), + (char *)ap->a_aclp, ap->a_td); + + /* + * Map lack of attribute definition in UFS_EXTATTR into lack of + * support for ACLs on the filesystem. + */ + if (error == ENOATTR) + return (EOPNOTSUPP); + + if (error != 0) + return (error); + + /* + * Now that the EA is successfully updated, update the + * inode and mark it as changed. + */ + ufs_sync_inode_from_nfs4acl(ap->a_aclp, ap->a_nentries, ip); + ip->i_flag |= IN_CHANGE; + + VN_KNOTE_UNLOCKED(ap->a_vp, NOTE_ATTRIB); + return (0); +} + #endif /* !UFS_ACL */ ==== //depot/projects/soc2008/trasz_nfs4acl/sys/ufs/ufs/ufs_vnops.c#2 (text+ko) ==== @@ -2102,6 +2102,14 @@ *ap->a_retval = 0; #endif break; + + case _ACL_ACE_ENABLED: + if (ap->a_vp->v_mount->mnt_flag & MNT_NFS4ACLS) + *ap->a_retval = 1; + else + *ap->a_retval = 0; + break; + case _PC_ACL_PATH_MAX: #ifdef UFS_ACL if (ap->a_vp->v_mount->mnt_flag & MNT_ACLS) @@ -2466,6 +2474,9 @@ .vop_setacl = ufs_setacl, .vop_aclcheck = ufs_aclcheck, #endif + .vop_getace = ufs_getace, + .vop_setace = ufs_setace, + .vop_getacecnt = ufs_getacecnt, }; struct vop_vector ufs_fifoops = { @@ -2494,4 +2505,7 @@ .vop_setacl = ufs_setacl, .vop_aclcheck = ufs_aclcheck, #endif + .vop_getace = ufs_getace, + .vop_setace = ufs_setace, + .vop_getacecnt = ufs_getacecnt, };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200805241851.m4OIpCnK076739>