summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/pseudofs/pseudofs.h2
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c2
-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
-rw-r--r--sys/security/lomac/lomacfs_vnops.c3
-rw-r--r--sys/sys/extattr.h12
-rw-r--r--sys/ufs/ufs/ufs_extattr.c51
10 files changed, 171 insertions, 200 deletions
diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h
index ba0a93b..4017978 100644
--- a/sys/fs/pseudofs/pseudofs.h
+++ b/sys/fs/pseudofs/pseudofs.h
@@ -138,7 +138,7 @@ typedef int (*pfs_ioctl_t)(PFS_IOCTL_ARGS);
#define PFS_GETEXTATTR_ARGS \
struct thread *td, struct proc *p, struct pfs_node *pn, \
int attrnamespace, const char *name, struct uio *uio, \
- struct ucred *cred
+ size_t *size, struct ucred *cred
#define PFS_GETEXTATTR_PROTO(name) \
int name(PFS_GETEXTATTR_ARGS);
struct ucred;
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index 0c8bdc3..42662ea 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -283,7 +283,7 @@ pfs_getextattr(struct vop_getextattr_args *va)
}
error = (pn->pn_getextattr)(curthread, proc, pn, va->a_attrnamespace,
- va->a_name, va->a_uio, va->a_cred);
+ va->a_name, va->a_uio, va->a_size, va->a_cred);
if (proc != NULL)
PRELE(proc);
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;
};
diff --git a/sys/security/lomac/lomacfs_vnops.c b/sys/security/lomac/lomacfs_vnops.c
index ca4a188..fb1c3f4 100644
--- a/sys/security/lomac/lomacfs_vnops.c
+++ b/sys/security/lomac/lomacfs_vnops.c
@@ -1053,6 +1053,7 @@ lomacfs_getextattr(
int a_attrnamespace;
const char *a_name;
struct uio *a_uio;
+ size_t *a_size;
struct ucred *a_cred;
struct thread *a_td;
} */ *ap
@@ -1065,7 +1066,7 @@ lomacfs_getextattr(
return (EPERM);
else
return (VOP_GETEXTATTR(VTOLVP(ap->a_vp), ap->a_attrnamespace,
- ap->a_name, ap->a_uio, ap->a_cred, ap->a_td));
+ ap->a_name, ap->a_uio, ap->a_size, ap->a_cred, ap->a_td));
}
static int
diff --git a/sys/sys/extattr.h b/sys/sys/extattr.h
index bca21bd..2d65624 100644
--- a/sys/sys/extattr.h
+++ b/sys/sys/extattr.h
@@ -55,14 +55,14 @@ int extattrctl(const char *_path, int _cmd, const char *_filename,
int extattr_delete_fd(int _fd, int _attrnamespace, const char *_attrname);
int extattr_delete_file(const char *_path, int _attrnamespace,
const char *_attrname);
-int extattr_get_fd(int _fd, int _attrnamespace, const char *_attrname,
- struct iovec *_iovp, unsigned _iovcnt);
-int extattr_get_file(const char *_path, int _attrnamespace,
- const char *_attrname, struct iovec *_iovp, unsigned _iovcnt);
+ssize_t extattr_get_fd(int _fd, int _attrnamespace, const char *_attrname,
+ void *_data, size_t _nbytes);
+ssize_t extattr_get_file(const char *_path, int _attrnamespace,
+ const char *_attrname, void *_data, size_t _nbytes);
int extattr_set_fd(int _fd, int _attrnamespace, const char *_attrname,
- struct iovec *_iovp, unsigned _iovcnt);
+ const void *_data, size_t _nbytes);
int extattr_set_file(const char *_path, int _attrnamespace,
- const char *_attrname, struct iovec *_iovp, unsigned _iovcnt);
+ const char *_attrname, const void *_data, size_t _nbytes);
__END_DECLS
#endif /* !_KERNEL */
diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c
index 71ed166..34e0bed 100644
--- a/sys/ufs/ufs/ufs_extattr.c
+++ b/sys/ufs/ufs/ufs_extattr.c
@@ -80,7 +80,8 @@ static int ufs_extattr_enable(struct ufsmount *ump, int attrnamespace,
static int ufs_extattr_disable(struct ufsmount *ump, int attrnamespace,
const char *attrname, struct thread *td);
static int ufs_extattr_get(struct vnode *vp, int attrnamespace,
- const char *name, struct uio *uio, struct ucred *cred, struct thread *td);
+ const char *name, struct uio *uio, size_t *size, struct ucred *cred,
+ struct thread *td);
static int ufs_extattr_set(struct vnode *vp, int attrnamespace,
const char *name, struct uio *uio, struct ucred *cred, struct thread *td);
static int ufs_extattr_rm(struct vnode *vp, int attrnamespace,
@@ -825,6 +826,7 @@ vop_getextattr {
IN int a_attrnamespace;
IN const char *a_name;
INOUT struct uio *a_uio;
+ OUT struct size_t *a_size;
IN struct ucred *a_cred;
IN struct thread *a_td;
};
@@ -837,7 +839,7 @@ vop_getextattr {
ufs_extattr_uepm_lock(ump, ap->a_td);
error = ufs_extattr_get(ap->a_vp, ap->a_attrnamespace, ap->a_name,
- ap->a_uio, ap->a_cred, ap->a_td);
+ ap->a_uio, ap->a_size, ap->a_cred, ap->a_td);
ufs_extattr_uepm_unlock(ump, ap->a_td);
@@ -850,7 +852,7 @@ vop_getextattr {
*/
static int
ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
- struct uio *uio, struct ucred *cred, struct thread *td)
+ struct uio *uio, size_t *size, struct ucred *cred, struct thread *td)
{
struct ufs_extattr_list_entry *attribute;
struct ufs_extattr_header ueh;
@@ -860,7 +862,7 @@ ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
struct ufsmount *ump = VFSTOUFS(mp);
struct inode *ip = VTOI(vp);
off_t base_offset;
- size_t size, old_size;
+ size_t len, old_len;
int error = 0;
if (!(ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED))
@@ -885,7 +887,7 @@ ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
* extended attribute semantic. Otherwise we can't guarantee
* atomicity, as we don't provide locks for extended attributes.
*/
- if (uio->uio_offset != 0)
+ if (uio != NULL && uio->uio_offset != 0)
return (ENXIO);
/*
@@ -956,27 +958,36 @@ ufs_extattr_get(struct vnode *vp, int attrnamespace, const char *name,
goto vopunlock_exit;
}
- /* Allow for offset into the attribute data. */
- uio->uio_offset = base_offset + sizeof(struct ufs_extattr_header);
+ /* Return full data size if caller requested it. */
+ if (size != NULL)
+ *size = ueh.ueh_len;
- /*
- * Figure out maximum to transfer -- use buffer size and local data
- * limit.
- */
- size = MIN(uio->uio_resid, ueh.ueh_len);
- old_size = uio->uio_resid;
- uio->uio_resid = size;
+ /* Return data if the caller requested it. */
+ if (uio != NULL) {
+ /* Allow for offset into the attribute data. */
+ uio->uio_offset = base_offset + sizeof(struct
+ ufs_extattr_header);
- error = VOP_READ(attribute->uele_backing_vnode, uio,
- IO_NODELOCKED, ump->um_extattr.uepm_ucred);
- if (error)
- goto vopunlock_exit;
+ /*
+ * Figure out maximum to transfer -- use buffer size and
+ * local data limit.
+ */
+ len = MIN(uio->uio_resid, ueh.ueh_len);
+ old_len = uio->uio_resid;
+ uio->uio_resid = len;
- uio->uio_resid = old_size - (size - uio->uio_resid);
+ error = VOP_READ(attribute->uele_backing_vnode, uio,
+ IO_NODELOCKED, ump->um_extattr.uepm_ucred);
+ if (error)
+ goto vopunlock_exit;
+
+ uio->uio_resid = old_len - (len - uio->uio_resid);
+ }
vopunlock_exit:
- uio->uio_offset = 0;
+ if (uio != NULL)
+ uio->uio_offset = 0;
if (attribute->uele_backing_vnode != vp)
VOP_UNLOCK(attribute->uele_backing_vnode, 0, td);
OpenPOWER on IntegriCloud