-/* $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 $ */
/*
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;
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
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))
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);
}
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;
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
/*
}
#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))
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);
}
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;
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
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))
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);
}
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;
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
/*
}
#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))
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);
}
-/* $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 $ */
/*
*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);
+}
+