PERFORCE change 142223 for review
Edward Tomasz Napierala
trasz at FreeBSD.org
Sat May 24 18:51:13 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=142223
Change 142223 by trasz at 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 at .
+ */
+#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,
};
More information about the p4-projects
mailing list