p{read,write}{,v} from csapuntz, partial NetBSD origin I think
authorderaadt <deraadt@openbsd.org>
Thu, 20 Apr 2000 06:32:00 +0000 (06:32 +0000)
committerderaadt <deraadt@openbsd.org>
Thu, 20 Apr 2000 06:32:00 +0000 (06:32 +0000)
sys/kern/sys_generic.c
sys/kern/vfs_syscalls.c
sys/sys/file.h

index c0a860a..75edfb6 100644 (file)
@@ -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);
 }
 
index 896640a..7979efa 100644 (file)
@@ -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);
+}
+
index 9b440e3..8ea132e 100644 (file)
@@ -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 */