diff options
author | rwatson <rwatson@FreeBSD.org> | 2003-06-04 03:57:28 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2003-06-04 03:57:28 +0000 |
commit | df2db1a4c277c2f4250ed3fccc2328a1dd2eded2 (patch) | |
tree | ea0d21d2d63692a39824dcc998643d480fbe458f /sys/kern | |
parent | bf8d163e59fc1ac917f933192757825e7e671d01 (diff) | |
download | FreeBSD-src-df2db1a4c277c2f4250ed3fccc2328a1dd2eded2.zip FreeBSD-src-df2db1a4c277c2f4250ed3fccc2328a1dd2eded2.tar.gz |
Implementations of extattr_list_fd(), extattr_list_file(), and
extattr_list_link() system calls, which return a least of extended
attributes defined for a vnode referenced by a file descriptor
or path name. Currently, we just invoke VOP_GETEXTATTR() since
it will convert a request for an empty name into a query for a
name list, which was the old (more hackish) API. At some point
in the near future, we'll push the distinction between get and
list down to the vnode operation layer, but this provides access
to the new API for applications in the short term.
Pointed out by: Dominic Giampaolo <dbg@apple.com>
Obtained from: TrustedBSD Project
Sponsored by: DARPA, Network Associates Laboratories
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_extattr.c | 143 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 143 |
2 files changed, 286 insertions, 0 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 8639ea6..8987fb7 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -4319,3 +4319,146 @@ extattr_delete_link(td, uap) vrele(nd.ni_vp); return(error); } + +/*- + * Retrieve a list of extended attributes on a file or directory. + * + * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace", + * userspace buffer pointer "data", buffer length "nbytes", + * thread "td". + * Returns: 0 on success, an error number otherwise + * Locks: none + * References: vp must be a valid reference for the duration of the call + */ +static int +extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, + size_t nbytes, struct thread *td) +{ + struct uio auio, *auiop; + size_t size, *sizep; + struct iovec aiov; + ssize_t cnt; + int error; + + VOP_LEASE(vp, td, td->td_ucred, LEASE_READ); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + + auiop = NULL; + sizep = NULL; + cnt = 0; + if (data != NULL) { + aiov.iov_base = data; + aiov.iov_len = nbytes; + auio.uio_iov = &aiov; + auio.uio_offset = 0; + if (nbytes > INT_MAX) { + error = EINVAL; + goto done; + } + auio.uio_resid = nbytes; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_td = td; + auiop = &auio; + cnt = nbytes; + } else + sizep = &size; + +#ifdef MAC + error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace, + "", &auio); + if (error) + goto done; +#endif + + error = VOP_GETEXTATTR(vp, attrnamespace, "", auiop, sizep, + td->td_ucred, td); + + if (auiop != NULL) { + cnt -= auio.uio_resid; + td->td_retval[0] = cnt; + } else + td->td_retval[0] = size; + +done: + VOP_UNLOCK(vp, 0, td); + return (error); +} + + +int +extattr_list_fd(td, uap) + struct thread *td; + struct extattr_list_fd_args /* { + int fd; + int attrnamespace; + void *data; + size_t nbytes; + } */ *uap; +{ + struct file *fp; + int error; + + error = getvnode(td->td_proc->p_fd, uap->fd, &fp); + if (error) + return (error); + + error = extattr_list_vp(fp->f_data, uap->attrnamespace, uap->data, + uap->nbytes, td); + + fdrop(fp, td); + return (error); +} + +int +extattr_list_file(td, uap) + struct thread*td; + struct extattr_list_file_args /* { + const char *path; + int attrnamespace; + void *data; + size_t nbytes; + } */ *uap; +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, + uap->nbytes, td); + + vrele(nd.ni_vp); + return (error); +} + +int +extattr_list_link(td, uap) + struct thread*td; + struct extattr_list_link_args /* { + const char *path; + int attrnamespace; + void *data; + size_t nbytes; + } */ *uap; +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, + uap->nbytes, td); + + vrele(nd.ni_vp); + return (error); +} + diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 8639ea6..8987fb7 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -4319,3 +4319,146 @@ extattr_delete_link(td, uap) vrele(nd.ni_vp); return(error); } + +/*- + * Retrieve a list of extended attributes on a file or directory. + * + * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace", + * userspace buffer pointer "data", buffer length "nbytes", + * thread "td". + * Returns: 0 on success, an error number otherwise + * Locks: none + * References: vp must be a valid reference for the duration of the call + */ +static int +extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, + size_t nbytes, struct thread *td) +{ + struct uio auio, *auiop; + size_t size, *sizep; + struct iovec aiov; + ssize_t cnt; + int error; + + VOP_LEASE(vp, td, td->td_ucred, LEASE_READ); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + + auiop = NULL; + sizep = NULL; + cnt = 0; + if (data != NULL) { + aiov.iov_base = data; + aiov.iov_len = nbytes; + auio.uio_iov = &aiov; + auio.uio_offset = 0; + if (nbytes > INT_MAX) { + error = EINVAL; + goto done; + } + auio.uio_resid = nbytes; + auio.uio_rw = UIO_READ; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_td = td; + auiop = &auio; + cnt = nbytes; + } else + sizep = &size; + +#ifdef MAC + error = mac_check_vnode_getextattr(td->td_ucred, vp, attrnamespace, + "", &auio); + if (error) + goto done; +#endif + + error = VOP_GETEXTATTR(vp, attrnamespace, "", auiop, sizep, + td->td_ucred, td); + + if (auiop != NULL) { + cnt -= auio.uio_resid; + td->td_retval[0] = cnt; + } else + td->td_retval[0] = size; + +done: + VOP_UNLOCK(vp, 0, td); + return (error); +} + + +int +extattr_list_fd(td, uap) + struct thread *td; + struct extattr_list_fd_args /* { + int fd; + int attrnamespace; + void *data; + size_t nbytes; + } */ *uap; +{ + struct file *fp; + int error; + + error = getvnode(td->td_proc->p_fd, uap->fd, &fp); + if (error) + return (error); + + error = extattr_list_vp(fp->f_data, uap->attrnamespace, uap->data, + uap->nbytes, td); + + fdrop(fp, td); + return (error); +} + +int +extattr_list_file(td, uap) + struct thread*td; + struct extattr_list_file_args /* { + const char *path; + int attrnamespace; + void *data; + size_t nbytes; + } */ *uap; +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, + uap->nbytes, td); + + vrele(nd.ni_vp); + return (error); +} + +int +extattr_list_link(td, uap) + struct thread*td; + struct extattr_list_link_args /* { + const char *path; + int attrnamespace; + void *data; + size_t nbytes; + } */ *uap; +{ + struct nameidata nd; + int error; + + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td); + error = namei(&nd); + if (error) + return (error); + NDFREE(&nd, NDF_ONLY_PNBUF); + + error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data, + uap->nbytes, td); + + vrele(nd.ni_vp); + return (error); +} + |