summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2000-04-20 06:32:01 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2000-04-20 06:32:01 +0000
commit030f32bd759685fb6ed00c6d7ecbd11568881e97 (patch)
tree3b9afd291a5f38ac4e182c6d13c7f2397f908174 /sys
parent5daa6db7ab63cc9df88473a4abb42ce1bc850645 (diff)
p{read,write}{,v} from csapuntz, partial NetBSD origin I think
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/sys_generic.c320
-rw-r--r--sys/kern/vfs_syscalls.c212
-rw-r--r--sys/sys/file.h12
3 files changed, 453 insertions, 91 deletions
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index c0a860abd60..75edfb6aefc 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_generic.c,v 1.23 2000/04/19 08:34:54 csapuntz Exp $ */
+/* $OpenBSD: sys_generic.c,v 1.24 2000/04/20 06:32:00 deraadt Exp $ */
/* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */
/*
@@ -77,13 +77,41 @@ sys_read(p, v, retval)
void *v;
register_t *retval;
{
- register struct sys_read_args /* {
+ struct sys_read_args /* {
syscallarg(int) fd;
syscallarg(void *) buf;
syscallarg(size_t) nbyte;
} */ *uap = v;
- register struct file *fp;
- register struct filedesc *fdp = p->p_fd;
+ int fd = SCARG(uap, fd);
+ struct file *fp;
+ struct filedesc *fdp = p->p_fd;
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+ /* dofileread() will unuse the descriptor for us */
+ return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
+ &fp->f_offset, retval));
+}
+
+int
+dofileread(p, fd, fp, buf, nbyte, offset, retval)
+ struct proc *p;
+ int fd;
+ struct file *fp;
+ void *buf;
+ size_t nbyte;
+ off_t *offset;
+ register_t *retval;
+{
struct uio auio;
struct iovec aiov;
long cnt, error = 0;
@@ -91,21 +119,25 @@ sys_read(p, v, retval)
struct iovec ktriov;
#endif
- if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
- (fp->f_flag & FREAD) == 0)
- return (EBADF);
- /* Don't allow nbyte to be larger than max return val */
- if (SCARG(uap, nbyte) > SSIZE_MAX)
- return(EINVAL);
- aiov.iov_base = (caddr_t)SCARG(uap, buf);
- aiov.iov_len = SCARG(uap, nbyte);
+ aiov.iov_base = (caddr_t)buf;
+ aiov.iov_len = nbyte;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
- auio.uio_resid = SCARG(uap, nbyte);
+ auio.uio_resid = nbyte;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
+
+ /*
+ * Reads return ssize_t because -1 is returned on error. Therefore
+ * we must restrict the length to SSIZE_MAX to avoid garbage return
+ * values.
+ */
+ if (auio.uio_resid > SSIZE_MAX) {
+ error = EINVAL;
+ goto out;
+ }
+
#ifdef KTRACE
/*
* if tracing, save a copy of iovec
@@ -113,8 +145,8 @@ sys_read(p, v, retval)
if (KTRPOINT(p, KTR_GENIO))
ktriov = aiov;
#endif
- cnt = SCARG(uap, nbyte);
- error = (*fp->f_ops->fo_read)(fp, &fp->f_offset, &auio, fp->f_cred);
+ cnt = auio.uio_resid;
+ error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred);
if (error)
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -122,10 +154,13 @@ sys_read(p, v, retval)
cnt -= auio.uio_resid;
#ifdef KTRACE
if (KTRPOINT(p, KTR_GENIO) && error == 0)
- ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, &ktriov,
- cnt, error);
+ ktrgenio(p->p_tracep, fd, UIO_READ, &ktriov, cnt, error);
#endif
*retval = cnt;
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
return (error);
}
@@ -138,15 +173,43 @@ sys_readv(p, v, retval)
void *v;
register_t *retval;
{
- register struct sys_readv_args /* {
+ struct sys_readv_args /* {
syscallarg(int) fd;
- syscallarg(struct iovec *) iovp;
+ syscallarg(const struct iovec *) iovp;
syscallarg(int) iovcnt;
} */ *uap = v;
- register struct file *fp;
- register struct filedesc *fdp = p->p_fd;
+ int fd = SCARG(uap, fd);
+ struct file *fp;
+ struct filedesc *fdp = p->p_fd;
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+ /* dofilereadv() will unuse the descriptor for us */
+ return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
+ &fp->f_offset, retval));
+}
+
+int
+dofilereadv(p, fd, fp, iovp, iovcnt, offset, retval)
+ struct proc *p;
+ int fd;
+ struct file *fp;
+ const struct iovec *iovp;
+ int iovcnt;
+ off_t *offset;
+ register_t *retval;
+{
struct uio auio;
- register struct iovec *iov;
+ struct iovec *iov;
struct iovec *needfree;
struct iovec aiov[UIO_SMALLIOV];
long i, cnt, error = 0;
@@ -155,39 +218,44 @@ sys_readv(p, v, retval)
struct iovec *ktriov = NULL;
#endif
- if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
- (fp->f_flag & FREAD) == 0)
- return (EBADF);
- if (SCARG(uap, iovcnt) <= 0)
- return (EINVAL);
/* note: can't use iovlen until iovcnt is validated */
- iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
- if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
- if (SCARG(uap, iovcnt) > IOV_MAX)
- return (EINVAL);
+ iovlen = iovcnt * sizeof(struct iovec);
+ if ((u_int)iovcnt > UIO_SMALLIOV) {
+ if ((u_int)iovcnt > IOV_MAX) {
+ error = EINVAL;
+ goto out;
+ }
MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
needfree = iov;
- } else {
+ } else if ((u_int)iovcnt > 0) {
iov = aiov;
needfree = NULL;
+ } else {
+ error = EINVAL;
+ goto out;
}
+
auio.uio_iov = iov;
- auio.uio_iovcnt = SCARG(uap, iovcnt);
+ auio.uio_iovcnt = iovcnt;
auio.uio_rw = UIO_READ;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
+ error = copyin(iovp, iov, iovlen);
if (error)
goto done;
auio.uio_resid = 0;
- for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
- /* Don't allow sum > SSIZE_MAX */
- if (iov->iov_len > SSIZE_MAX ||
- (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
+ for (i = 0; i < iovcnt; i++) {
+ auio.uio_resid += iov->iov_len;
+ /*
+ * Reads return ssize_t because -1 is returned on error.
+ * Therefore we must restrict the length to SSIZE_MAX to
+ * avoid garbage return values.
+ */
+ if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
error = EINVAL;
goto done;
}
+ iov++;
}
#ifdef KTRACE
/*
@@ -199,7 +267,7 @@ sys_readv(p, v, retval)
}
#endif
cnt = auio.uio_resid;
- error = (*fp->f_ops->fo_read)(fp, &fp->f_offset, &auio, fp->f_cred);
+ error = (*fp->f_ops->fo_read)(fp, offset, &auio, fp->f_cred);
if (error)
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -207,16 +275,20 @@ sys_readv(p, v, retval)
cnt -= auio.uio_resid;
#ifdef KTRACE
if (ktriov != NULL) {
- if (error == 0)
- ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_READ, ktriov,
- cnt, error);
+ if (error == 0)
+ ktrgenio(p->p_tracep, fd, UIO_READ, ktriov, cnt,
+ error);
FREE(ktriov, M_TEMP);
}
#endif
*retval = cnt;
-done:
+ done:
if (needfree)
FREE(needfree, M_IOV);
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
return (error);
}
@@ -229,13 +301,41 @@ sys_write(p, v, retval)
void *v;
register_t *retval;
{
- register struct sys_write_args /* {
+ struct sys_write_args /* {
syscallarg(int) fd;
- syscallarg(void *) buf;
+ syscallarg(const void *) buf;
syscallarg(size_t) nbyte;
} */ *uap = v;
- register struct file *fp;
- register struct filedesc *fdp = p->p_fd;
+ int fd = SCARG(uap, fd);
+ struct file *fp;
+ struct filedesc *fdp = p->p_fd;
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FWRITE) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+ /* dofilewrite() will unuse the descriptor for us */
+ return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
+ &fp->f_offset, retval));
+}
+
+int
+dofilewrite(p, fd, fp, buf, nbyte, offset, retval)
+ struct proc *p;
+ int fd;
+ struct file *fp;
+ const void *buf;
+ size_t nbyte;
+ off_t *offset;
+ register_t *retval;
+{
struct uio auio;
struct iovec aiov;
long cnt, error = 0;
@@ -243,21 +343,25 @@ sys_write(p, v, retval)
struct iovec ktriov;
#endif
- if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
- (fp->f_flag & FWRITE) == 0)
- return (EBADF);
- /* Don't allow nbyte to be larger than max return val */
- if (SCARG(uap, nbyte) > SSIZE_MAX)
- return(EINVAL);
- aiov.iov_base = (caddr_t)SCARG(uap, buf);
- aiov.iov_len = SCARG(uap, nbyte);
+ aiov.iov_base = (caddr_t)buf; /* XXX kills const */
+ aiov.iov_len = nbyte;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
- auio.uio_resid = SCARG(uap, nbyte);
+ auio.uio_resid = nbyte;
auio.uio_rw = UIO_WRITE;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
+
+ /*
+ * Writes return ssize_t because -1 is returned on error. Therefore
+ * we must restrict the length to SSIZE_MAX to avoid garbage return
+ * values.
+ */
+ if (auio.uio_resid > SSIZE_MAX) {
+ error = EINVAL;
+ goto out;
+ }
+
#ifdef KTRACE
/*
* if tracing, save a copy of iovec
@@ -265,8 +369,8 @@ sys_write(p, v, retval)
if (KTRPOINT(p, KTR_GENIO))
ktriov = aiov;
#endif
- cnt = SCARG(uap, nbyte);
- error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio, fp->f_cred);
+ cnt = auio.uio_resid;
+ error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred);
if (error) {
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -277,10 +381,13 @@ sys_write(p, v, retval)
cnt -= auio.uio_resid;
#ifdef KTRACE
if (KTRPOINT(p, KTR_GENIO) && error == 0)
- ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
- &ktriov, cnt, error);
+ ktrgenio(p->p_tracep, fd, UIO_WRITE, &ktriov, cnt, error);
#endif
*retval = cnt;
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
return (error);
}
@@ -293,15 +400,43 @@ sys_writev(p, v, retval)
void *v;
register_t *retval;
{
- register struct sys_writev_args /* {
+ struct sys_writev_args /* {
syscallarg(int) fd;
- syscallarg(struct iovec *) iovp;
+ syscallarg(const struct iovec *) iovp;
syscallarg(int) iovcnt;
} */ *uap = v;
- register struct file *fp;
- register struct filedesc *fdp = p->p_fd;
+ int fd = SCARG(uap, fd);
+ struct file *fp;
+ struct filedesc *fdp = p->p_fd;
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FWRITE) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+ /* dofilewritev() will unuse the descriptor for us */
+ return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
+ &fp->f_offset, retval));
+}
+
+int
+dofilewritev(p, fd, fp, iovp, iovcnt, offset, retval)
+ struct proc *p;
+ int fd;
+ struct file *fp;
+ const struct iovec *iovp;
+ int iovcnt;
+ off_t *offset;
+ register_t *retval;
+{
struct uio auio;
- register struct iovec *iov;
+ struct iovec *iov;
struct iovec *needfree;
struct iovec aiov[UIO_SMALLIOV];
long i, cnt, error = 0;
@@ -310,39 +445,42 @@ sys_writev(p, v, retval)
struct iovec *ktriov = NULL;
#endif
- if (((u_int)SCARG(uap, fd)) >= fdp->fd_nfiles ||
- (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
- (fp->f_flag & FWRITE) == 0)
- return (EBADF);
- if (SCARG(uap, iovcnt) <= 0)
- return (EINVAL);
/* note: can't use iovlen until iovcnt is validated */
- iovlen = SCARG(uap, iovcnt) * sizeof (struct iovec);
- if (SCARG(uap, iovcnt) > UIO_SMALLIOV) {
- if (SCARG(uap, iovcnt) > IOV_MAX)
+ iovlen = iovcnt * sizeof(struct iovec);
+ if ((u_int)iovcnt > UIO_SMALLIOV) {
+ if ((u_int)iovcnt > IOV_MAX)
return (EINVAL);
MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
needfree = iov;
- } else {
+ } else if ((u_int)iovcnt > 0) {
iov = aiov;
needfree = NULL;
+ } else {
+ error = EINVAL;
+ goto out;
}
+
auio.uio_iov = iov;
- auio.uio_iovcnt = SCARG(uap, iovcnt);
+ auio.uio_iovcnt = iovcnt;
auio.uio_rw = UIO_WRITE;
auio.uio_segflg = UIO_USERSPACE;
auio.uio_procp = p;
- error = copyin((caddr_t)SCARG(uap, iovp), (caddr_t)iov, iovlen);
+ error = copyin(iovp, iov, iovlen);
if (error)
goto done;
auio.uio_resid = 0;
- for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) {
- /* Don't allow sum > SSIZE_MAX */
- if (iov->iov_len > SSIZE_MAX ||
- (auio.uio_resid += iov->iov_len) > SSIZE_MAX) {
+ for (i = 0; i < iovcnt; i++) {
+ auio.uio_resid += iov->iov_len;
+ /*
+ * Writes return ssize_t because -1 is returned on error.
+ * Therefore we must restrict the length to SSIZE_MAX to
+ * avoid garbage return values.
+ */
+ if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
error = EINVAL;
goto done;
}
+ iov++;
}
#ifdef KTRACE
/*
@@ -354,7 +492,7 @@ sys_writev(p, v, retval)
}
#endif
cnt = auio.uio_resid;
- error = (*fp->f_ops->fo_write)(fp, &fp->f_offset, &auio, fp->f_cred);
+ error = (*fp->f_ops->fo_write)(fp, offset, &auio, fp->f_cred);
if (error) {
if (auio.uio_resid != cnt && (error == ERESTART ||
error == EINTR || error == EWOULDBLOCK))
@@ -365,16 +503,20 @@ sys_writev(p, v, retval)
cnt -= auio.uio_resid;
#ifdef KTRACE
if (ktriov != NULL) {
- if (error == 0)
- ktrgenio(p->p_tracep, SCARG(uap, fd), UIO_WRITE,
- ktriov, cnt, error);
+ if (error == 0)
+ ktrgenio(p->p_tracep, fd, UIO_WRITE, ktriov, cnt,
+ error);
FREE(ktriov, M_TEMP);
}
#endif
*retval = cnt;
-done:
+ done:
if (needfree)
FREE(needfree, M_IOV);
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
return (error);
}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 896640a6198..7979efaf68b 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_syscalls.c,v 1.64 2000/04/15 19:52:48 csapuntz Exp $ */
+/* $OpenBSD: vfs_syscalls.c,v 1.65 2000/04/20 06:32:00 deraadt Exp $ */
/* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */
/*
@@ -2797,3 +2797,213 @@ sys_ogetfsstat(p, v, retval)
*retval = count;
return (0);
}
+
+
+/*
+ * Positional read system call.
+ */
+int
+sys_pread(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_pread_args /* {
+ syscallarg(int) fd;
+ syscallarg(void *) buf;
+ syscallarg(size_t) nbyte;
+ syscallarg(off_t) offset;
+ } */ *uap = v;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct vnode *vp;
+ off_t offset;
+ int error, fd = SCARG(uap, fd);
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+
+ vp = (struct vnode *)fp->f_data;
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ error = ESPIPE;
+ goto out;
+ }
+
+ offset = SCARG(uap, offset);
+
+ /* dofileread() will unuse the descriptor for us */
+ return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
+ &offset, retval));
+
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
+ return (error);
+}
+
+/*
+ * Positional scatter read system call.
+ */
+int
+sys_preadv(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_preadv_args /* {
+ syscallarg(int) fd;
+ syscallarg(const struct iovec *) iovp;
+ syscallarg(int) iovcnt;
+ syscallarg(off_t) offset;
+ } */ *uap = v;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct vnode *vp;
+ off_t offset;
+ int error, fd = SCARG(uap, fd);
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FREAD) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+
+ vp = (struct vnode *)fp->f_data;
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ error = ESPIPE;
+ goto out;
+ }
+
+ offset = SCARG(uap, offset);
+
+ /* dofilereadv() will unuse the descriptor for us */
+ return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
+ &offset, retval));
+
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
+ return (error);
+}
+
+/*
+ * Positional write system call.
+ */
+int
+sys_pwrite(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_pwrite_args /* {
+ syscallarg(int) fd;
+ syscallarg(const void *) buf;
+ syscallarg(size_t) nbyte;
+ syscallarg(off_t) offset;
+ } */ *uap = v;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct vnode *vp;
+ off_t offset;
+ int error, fd = SCARG(uap, fd);
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FWRITE) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+
+ vp = (struct vnode *)fp->f_data;
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ error = ESPIPE;
+ goto out;
+ }
+
+ offset = SCARG(uap, offset);
+
+ /* dofilewrite() will unuse the descriptor for us */
+ return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
+ &offset, retval));
+
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
+ return (error);
+}
+
+
+/*
+ * Positional gather write system call.
+ */
+int
+sys_pwritev(p, v, retval)
+ struct proc *p;
+ void *v;
+ register_t *retval;
+{
+ struct sys_pwritev_args /* {
+ syscallarg(int) fd;
+ syscallarg(const struct iovec *) iovp;
+ syscallarg(int) iovcnt;
+ syscallarg(off_t) offset;
+ } */ *uap = v;
+ struct filedesc *fdp = p->p_fd;
+ struct file *fp;
+ struct vnode *vp;
+ off_t offset;
+ int error, fd = SCARG(uap, fd);
+
+ if ((u_int)fd >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[fd]) == NULL ||
+#if notyet
+ (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
+#endif
+ (fp->f_flag & FWRITE) == 0)
+ return (EBADF);
+
+#if notyet
+ FILE_USE(fp);
+#endif
+ vp = (struct vnode *)fp->f_data;
+ if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
+ error = ESPIPE;
+ goto out;
+ }
+
+ offset = SCARG(uap, offset);
+
+ /* dofilewritev() will unuse the descriptor for us */
+ return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
+ &offset, retval));
+
+ out:
+#if notyet
+ FILE_UNUSE(fp, p);
+#endif
+ return (error);
+}
+
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 9b440e30e3a..8ea132e4d8c 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: file.h,v 1.6 2000/04/19 08:34:50 csapuntz Exp $ */
+/* $OpenBSD: file.h,v 1.7 2000/04/20 06:32:00 deraadt Exp $ */
/* $NetBSD: file.h,v 1.11 1995/03/26 20:24:13 jtc Exp $ */
/*
@@ -82,4 +82,14 @@ extern int maxfiles; /* kernel limit on number of open files */
extern int nfiles; /* actual number of open files */
extern struct fileops vnops; /* vnode operations for files */
+int dofileread __P((struct proc *, int, struct file *, void *, size_t,
+ off_t *, register_t *));
+int dofilewrite __P((struct proc *, int, struct file *, const void *,
+ size_t, off_t *, register_t *));
+
+int dofilereadv __P((struct proc *, int, struct file *,
+ const struct iovec *, int, off_t *, register_t *));
+int dofilewritev __P((struct proc *, int, struct file *,
+ const struct iovec *, int, off_t *, register_t *));
+
#endif /* _KERNEL */