+ if (((unsigned)uap->fdes) >= NOFILE ||
+ (fp = u.u_ofile[uap->fdes]) == NULL ||
+ (fp->f_flag & FREAD) == 0)
+ RETURN (EBADF);
+ if (uap->count < 0)
+ RETURN (EINVAL);
+ aiov.iov_base = (caddr_t)uap->cbuf;
+ aiov.iov_len = uap->count;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_resid = uap->count;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_USERSPACE;
+#ifdef KTRACE
+ /*
+ * if tracing, save a copy of iovec
+ */
+ if (KTRPOINT(u.u_procp, KTR_GENIO))
+ ktriov = aiov;
+#endif
+ cnt = uap->count;
+ if (setjmp(&u.u_qsave)) {
+ if (auio.uio_resid == cnt) {
+ if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
+ error = EINTR;
+ else
+ u.u_eosys = RESTARTSYS;
+ }
+ } else
+ error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred);
+ cnt -= auio.uio_resid;
+#ifdef KTRACE
+ if (KTRPOINT(u.u_procp, KTR_GENIO))
+ ktrgenio(u.u_procp->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt);
+#endif
+ u.u_r.r_val1 = cnt;
+ RETURN (error);
+}
+
+readv()
+{
+ register struct a {
+ int fdes;
+ struct iovec *iovp;
+ unsigned iovcnt;
+ } *uap = (struct a *)u.u_ap;
+ register struct file *fp;
+ struct uio auio;
+ register struct iovec *iov;
+ struct iovec aiov[UIO_SMALLIOV];
+ long i, cnt, error = 0;
+#ifdef KTRACE
+ struct iovec *ktriov = NULL;
+#endif
+
+ if (((unsigned)uap->fdes) >= NOFILE ||
+ (fp = u.u_ofile[uap->fdes]) == NULL ||
+ (fp->f_flag & FREAD) == 0)
+ RETURN (EBADF);
+ if (uap->iovcnt > UIO_SMALLIOV) {
+ if (uap->iovcnt > UIO_MAXIOV)
+ RETURN (EINVAL);
+ MALLOC(iov, struct iovec *,
+ sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK);
+ } else
+ iov = aiov;
+ auio.uio_iov = iov;
+ auio.uio_iovcnt = uap->iovcnt;
+ auio.uio_rw = UIO_READ;
+ auio.uio_segflg = UIO_USERSPACE;
+ if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov,
+ uap->iovcnt * sizeof (struct iovec)))
+ goto done;
+ auio.uio_resid = 0;
+ for (i = 0; i < uap->iovcnt; i++) {
+ if (iov->iov_len < 0) {
+ error = EINVAL;
+ goto done;
+ }
+ auio.uio_resid += iov->iov_len;
+ if (auio.uio_resid < 0) {
+ error = EINVAL;
+ goto done;
+ }
+ iov++;