summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2003-06-04 03:57:28 +0000
committerrwatson <rwatson@FreeBSD.org>2003-06-04 03:57:28 +0000
commitdf2db1a4c277c2f4250ed3fccc2328a1dd2eded2 (patch)
treeea0d21d2d63692a39824dcc998643d480fbe458f /sys/kern/vfs_extattr.c
parentbf8d163e59fc1ac917f933192757825e7e671d01 (diff)
downloadFreeBSD-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/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c143
1 files changed, 143 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);
+}
+
OpenPOWER on IntegriCloud