summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2002-02-10 04:43:22 +0000
committerrwatson <rwatson@FreeBSD.org>2002-02-10 04:43:22 +0000
commit6ca91a055cc0b7ae8fca8dc8f4f4588898cd0eab (patch)
treee9458f6a52b269cdc1552a27ae5ddf17ae6024ee /sys/kern
parenta752dc58a831465c48efeea646d4fb6a555f80b7 (diff)
downloadFreeBSD-src-6ca91a055cc0b7ae8fca8dc8f4f4588898cd0eab.zip
FreeBSD-src-6ca91a055cc0b7ae8fca8dc8f4f4588898cd0eab.tar.gz
Part I: Update extended attribute API and ABI:
o Modify the system call syntax for extattr_{get,set}_{fd,file}() so as not to use the scatter gather API (which appeared not to be used by any consumers, and be less portable), rather, accepts 'data' and 'nbytes' in the style of other simple read/write interfaces. This changes the API and ABI. o Modify system call semantics so that extattr_get_{fd,file}() return a size_t. When performing a read, the number of bytes read will be returned, unless the data pointer is NULL, in which case the number of bytes of data are returned. This changes the API only. o Modify the VOP_GETEXTATTR() vnode operation to accept a *size_t argument so as to return the size, if desirable. If set to NULL, the size will not be returned. o Update various filesystems (pseodofs, ufs) to DTRT. These changes should make extended attributes more useful and more portable. More commits to rebuild the system call files, as well as update userland utilities to follow. Obtained from: TrustedBSD Project Sponsored by: DARPA, NAI Labs
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/syscalls.master15
-rw-r--r--sys/kern/vfs_extattr.c141
-rw-r--r--sys/kern/vfs_syscalls.c141
-rw-r--r--sys/kern/vfs_vnops.c3
-rw-r--r--sys/kern/vnode_if.src1
5 files changed, 130 insertions, 171 deletions
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 92aecac..c534546 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -513,10 +513,10 @@
const char *attrname); }
356 STD BSD { int extattr_set_file(const char *path, \
int attrnamespace, const char *attrname, \
- struct iovec *iovp, unsigned iovcnt); }
-357 STD BSD { int extattr_get_file(const char *path, \
+ void *data, size_t nbytes); }
+357 STD BSD { ssize_t extattr_get_file(const char *path, \
int attrnamespace, const char *attrname, \
- struct iovec *iovp, unsigned iovcnt); }
+ void *data, size_t nbytes); }
358 STD BSD { int extattr_delete_file(const char *path, \
int attrnamespace, const char *attrname); }
359 NOSTD BSD { int aio_waitcomplete(struct aiocb **aiocbp, struct timespec *timeout); }
@@ -535,11 +535,10 @@
369 STD BSD { int __cap_set_file(const char *path_p, struct cap *cap_p); }
370 NODEF NOHIDE lkmressys lkmressys nosys_args int
371 STD BSD { int extattr_set_fd(int fd, int attrnamespace, \
- const char *attrname, struct iovec *iovp, \
- int iovcnt); }
-372 STD BSD { int extattr_get_fd(int fd, int attrnamespace, \
- const char *attrname, struct iovec *iovp, \
- int iovcnt); }
+ const char *attrname, void *data, \
+ size_t nbytes); }
+372 STD BSD { ssize_t extattr_get_fd(int fd, int attrnamespace, \
+ const char *attrname, void *data, size_t nbytes); }
373 STD BSD { int extattr_delete_fd(int fd, int attrnamespace, \
const char *attrname); }
374 MSTD BSD { int __setugid(int flag); }
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 0500dde..67cec3e 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -3993,67 +3993,52 @@ extattrctl(td, uap)
return (error);
}
-/*
- * extattr_set_vp(): Set a named extended attribute on a file or directory
+/*-
+ * Set a named extended attribute on a file or directory
*
* Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname",
- * userspace iovec array pointer "iovp", unsigned int iovcnt
- * proc "p"
+ * kernelspace string pointer "attrname", 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_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- struct iovec *iovp, unsigned iovcnt, struct thread *td)
+ const void *data, size_t nbytes, struct thread *td)
{
struct mount *mp;
struct uio auio;
- struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
- u_int iovlen, cnt;
- int error, i;
+ struct iovec aiov;
+ ssize_t cnt;
+ int error;
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- iovlen = iovcnt * sizeof(struct iovec);
- if (iovcnt > UIO_SMALLIOV) {
- if (iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
- }
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else
- iov = aiov;
- auio.uio_iov = iov;
- auio.uio_iovcnt = iovcnt;
- auio.uio_rw = UIO_WRITE;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
+ aiov.iov_base = data;
+ aiov.iov_len = nbytes;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
auio.uio_offset = 0;
- if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen)))
+ if (nbytes > INT_MAX) {
+ error = EINVAL;
goto done;
- auio.uio_resid = 0;
- for (i = 0; i < iovcnt; i++) {
- if (iov->iov_len > INT_MAX - auio.uio_resid) {
- error = EINVAL;
- goto done;
- }
- auio.uio_resid += iov->iov_len;
- iov++;
}
- cnt = auio.uio_resid;
+ auio.uio_resid = nbytes;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_td = td;
+ cnt = nbytes;
+
error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
td->td_proc->p_ucred, td);
cnt -= auio.uio_resid;
td->td_retval[0] = cnt;
+
done:
- if (needfree)
- FREE(needfree, M_IOV);
VOP_UNLOCK(vp, 0, td);
vn_finished_write(mp);
return (error);
@@ -4079,7 +4064,7 @@ extattr_set_file(td, uap)
NDFREE(&nd, NDF_ONLY_PNBUF);
error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
- SCARG(uap, iovp), SCARG(uap, iovcnt), td);
+ SCARG(uap, data), SCARG(uap, nbytes), td);
vrele(nd.ni_vp);
return (error);
@@ -4103,71 +4088,65 @@ extattr_set_fd(td, uap)
return (error);
error = extattr_set_vp((struct vnode *)fp->f_data,
- SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp),
- SCARG(uap, iovcnt), td);
+ SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
+ SCARG(uap, nbytes), td);
fdrop(fp, td);
return (error);
}
-/*
- * extattr_get_vp(): Get a named extended attribute on a file or directory
+/*-
+ * Get a named extended attribute on a file or directory
*
* Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname",
- * userspace iovec array pointer "iovp", unsigned int iovcnt,
- * proc "p"
+ * kernelspace string pointer "attrname", 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_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- struct iovec *iovp, unsigned iovcnt, struct thread *td)
+ void *data, size_t nbytes, struct thread *td)
{
struct uio auio;
- struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
- u_int iovlen, cnt;
- int error, i;
+ struct iovec aiov;
+ ssize_t cnt;
+ size_t size;
+ int error;
VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- iovlen = iovcnt * sizeof (struct iovec);
- if (iovcnt > UIO_SMALLIOV) {
- if (iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
- }
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else
- iov = aiov;
- auio.uio_iov = iov;
- auio.uio_iovcnt = iovcnt;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
- auio.uio_offset = 0;
- if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen)))
- goto done;
- auio.uio_resid = 0;
- for (i = 0; i < iovcnt; i++) {
- if (iov->iov_len > INT_MAX - auio.uio_resid) {
+ /*
+ * Slightly unusual semantics: if the user provides a NULL data
+ * pointer, they don't want to receive the data, just the
+ * maximum read length.
+ */
+ 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 += iov->iov_len;
- iov++;
+ auio.uio_resid = nbytes;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_td = td;
+ cnt = nbytes;
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
+ NULL, td->td_proc->p_ucred, td);
+ cnt -= auio.uio_resid;
+ td->td_retval[0] = cnt;
+ } else {
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
+ &size, td->td_proc->p_ucred, td);
+ td->td_retval[0] = size;
}
- cnt = auio.uio_resid;
- error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
- td->td_proc->p_ucred, td);
- cnt -= auio.uio_resid;
- td->td_retval[0] = cnt;
done:
- if (needfree)
- FREE(needfree, M_IOV);
VOP_UNLOCK(vp, 0, td);
return (error);
}
@@ -4192,7 +4171,7 @@ extattr_get_file(td, uap)
NDFREE(&nd, NDF_ONLY_PNBUF);
error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
- SCARG(uap, iovp), SCARG(uap, iovcnt), td);
+ SCARG(uap, data), SCARG(uap, nbytes), td);
vrele(nd.ni_vp);
return (error);
@@ -4216,8 +4195,8 @@ extattr_get_fd(td, uap)
return (error);
error = extattr_get_vp((struct vnode *)fp->f_data,
- SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp),
- SCARG(uap, iovcnt), td);
+ SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
+ SCARG(uap, nbytes), td);
fdrop(fp, td);
return (error);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 0500dde..67cec3e 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3993,67 +3993,52 @@ extattrctl(td, uap)
return (error);
}
-/*
- * extattr_set_vp(): Set a named extended attribute on a file or directory
+/*-
+ * Set a named extended attribute on a file or directory
*
* Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname",
- * userspace iovec array pointer "iovp", unsigned int iovcnt
- * proc "p"
+ * kernelspace string pointer "attrname", 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_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- struct iovec *iovp, unsigned iovcnt, struct thread *td)
+ const void *data, size_t nbytes, struct thread *td)
{
struct mount *mp;
struct uio auio;
- struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
- u_int iovlen, cnt;
- int error, i;
+ struct iovec aiov;
+ ssize_t cnt;
+ int error;
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- iovlen = iovcnt * sizeof(struct iovec);
- if (iovcnt > UIO_SMALLIOV) {
- if (iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
- }
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else
- iov = aiov;
- auio.uio_iov = iov;
- auio.uio_iovcnt = iovcnt;
- auio.uio_rw = UIO_WRITE;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
+ aiov.iov_base = data;
+ aiov.iov_len = nbytes;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
auio.uio_offset = 0;
- if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen)))
+ if (nbytes > INT_MAX) {
+ error = EINVAL;
goto done;
- auio.uio_resid = 0;
- for (i = 0; i < iovcnt; i++) {
- if (iov->iov_len > INT_MAX - auio.uio_resid) {
- error = EINVAL;
- goto done;
- }
- auio.uio_resid += iov->iov_len;
- iov++;
}
- cnt = auio.uio_resid;
+ auio.uio_resid = nbytes;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_td = td;
+ cnt = nbytes;
+
error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
td->td_proc->p_ucred, td);
cnt -= auio.uio_resid;
td->td_retval[0] = cnt;
+
done:
- if (needfree)
- FREE(needfree, M_IOV);
VOP_UNLOCK(vp, 0, td);
vn_finished_write(mp);
return (error);
@@ -4079,7 +4064,7 @@ extattr_set_file(td, uap)
NDFREE(&nd, NDF_ONLY_PNBUF);
error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
- SCARG(uap, iovp), SCARG(uap, iovcnt), td);
+ SCARG(uap, data), SCARG(uap, nbytes), td);
vrele(nd.ni_vp);
return (error);
@@ -4103,71 +4088,65 @@ extattr_set_fd(td, uap)
return (error);
error = extattr_set_vp((struct vnode *)fp->f_data,
- SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp),
- SCARG(uap, iovcnt), td);
+ SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
+ SCARG(uap, nbytes), td);
fdrop(fp, td);
return (error);
}
-/*
- * extattr_get_vp(): Get a named extended attribute on a file or directory
+/*-
+ * Get a named extended attribute on a file or directory
*
* Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
- * kernelspace string pointer "attrname",
- * userspace iovec array pointer "iovp", unsigned int iovcnt,
- * proc "p"
+ * kernelspace string pointer "attrname", 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_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
- struct iovec *iovp, unsigned iovcnt, struct thread *td)
+ void *data, size_t nbytes, struct thread *td)
{
struct uio auio;
- struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
- u_int iovlen, cnt;
- int error, i;
+ struct iovec aiov;
+ ssize_t cnt;
+ size_t size;
+ int error;
VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
- iovlen = iovcnt * sizeof (struct iovec);
- if (iovcnt > UIO_SMALLIOV) {
- if (iovcnt > UIO_MAXIOV) {
- error = EINVAL;
- goto done;
- }
- MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
- needfree = iov;
- } else
- iov = aiov;
- auio.uio_iov = iov;
- auio.uio_iovcnt = iovcnt;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
- auio.uio_offset = 0;
- if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen)))
- goto done;
- auio.uio_resid = 0;
- for (i = 0; i < iovcnt; i++) {
- if (iov->iov_len > INT_MAX - auio.uio_resid) {
+ /*
+ * Slightly unusual semantics: if the user provides a NULL data
+ * pointer, they don't want to receive the data, just the
+ * maximum read length.
+ */
+ 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 += iov->iov_len;
- iov++;
+ auio.uio_resid = nbytes;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_USERSPACE;
+ auio.uio_td = td;
+ cnt = nbytes;
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
+ NULL, td->td_proc->p_ucred, td);
+ cnt -= auio.uio_resid;
+ td->td_retval[0] = cnt;
+ } else {
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, NULL,
+ &size, td->td_proc->p_ucred, td);
+ td->td_retval[0] = size;
}
- cnt = auio.uio_resid;
- error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio,
- td->td_proc->p_ucred, td);
- cnt -= auio.uio_resid;
- td->td_retval[0] = cnt;
done:
- if (needfree)
- FREE(needfree, M_IOV);
VOP_UNLOCK(vp, 0, td);
return (error);
}
@@ -4192,7 +4171,7 @@ extattr_get_file(td, uap)
NDFREE(&nd, NDF_ONLY_PNBUF);
error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
- SCARG(uap, iovp), SCARG(uap, iovcnt), td);
+ SCARG(uap, data), SCARG(uap, nbytes), td);
vrele(nd.ni_vp);
return (error);
@@ -4216,8 +4195,8 @@ extattr_get_fd(td, uap)
return (error);
error = extattr_get_vp((struct vnode *)fp->f_data,
- SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp),
- SCARG(uap, iovcnt), td);
+ SCARG(uap, attrnamespace), attrname, SCARG(uap, data),
+ SCARG(uap, nbytes), td);
fdrop(fp, td);
return (error);
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index c411bfc..d7c4bc8 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -905,7 +905,8 @@ vn_extattr_get(struct vnode *vp, int ioflg, int attrnamespace,
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
/* authorize attribute retrieval as kernel */
- error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, td);
+ error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, NULL, NULL,
+ td);
if ((ioflg & IO_NODELOCKED) == 0)
VOP_UNLOCK(vp, 0, td);
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index 43ff6b5..460d5b8 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -512,6 +512,7 @@ vop_getextattr {
IN int attrnamespace;
IN const char *name;
INOUT struct uio *uio;
+ OUT size_t *size;
IN struct ucred *cred;
IN struct thread *td;
};
OpenPOWER on IntegriCloud