diff options
author | jhb <jhb@FreeBSD.org> | 2005-03-31 22:56:14 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2005-03-31 22:56:14 +0000 |
commit | a9a1057e5e88beb273b050d301ed4b315a6fbc5f (patch) | |
tree | b293ea5b89d830b18d6e272eb20392c21add3a54 /sys/alpha | |
parent | 76cb101294622496d32b4a3b91c71aa3fb9e5e01 (diff) | |
download | FreeBSD-src-a9a1057e5e88beb273b050d301ed4b315a6fbc5f.zip FreeBSD-src-a9a1057e5e88beb273b050d301ed4b315a6fbc5f.tar.gz |
Use a custom version of copyinuio() to implement osf1_{read,write}v() via
kern_{read,write}v().
Diffstat (limited to 'sys/alpha')
-rw-r--r-- | sys/alpha/osf1/osf1_misc.c | 135 |
1 files changed, 56 insertions, 79 deletions
diff --git a/sys/alpha/osf1/osf1_misc.c b/sys/alpha/osf1/osf1_misc.c index f536108..584ed22 100644 --- a/sys/alpha/osf1/osf1_misc.c +++ b/sys/alpha/osf1/osf1_misc.c @@ -993,52 +993,61 @@ struct osf1_iovec { char *iov_base; int iov_len; }; -#define STACKGAPLEN 400 + +static int +osf1_copyinuio(struct osf1_iovec *iovp, u_int iovcnt, struct uio **uiop) +{ + struct osf1_iovec oiov; + struct iovec *iov; + struct uio *uio; + u_int iovlen; + int error, i; + + *uiop = NULL; + if (iovcnt > UIO_MAXIOV) + return (EINVAL); + iovlen = iovcnt * sizeof(struct iovec); + uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); + iov = (struct iovec *)(uio + 1); + for (i = 0; i < iovcnt; i++) { + error = copyin(&iovp[i], &oiov, sizeof(struct osf1_iovec)); + if (error) { + free(uio, M_IOV); + return (error); + } + iov[i].iov_base = oiov.iov_base; + iov[i].iov_len = oiov.iov_len; + } + uio->uio_iov = iov; + uio->uio_iovcnt = iovcnt; + uio->uio_segflg = UIO_USERSPACE; + uio->uio_offset = -1; + uio->uio_resid = 0; + for (i = 0; i < iovcnt; i++) { + if (iov->iov_len > INT_MAX - uio->uio_resid) { + free(uio, M_IOV); + return (EINVAL); + } + uio->uio_resid += iov->iov_len; + iov++; + } + *uiop = uio; + return (0); +} + int osf1_readv(td, uap) struct thread *td; struct osf1_readv_args *uap; { - int error, osize, nsize, i; - caddr_t sg; - struct readv_args /* { - syscallarg(int) fd; - syscallarg(struct iovec *) iovp; - syscallarg(u_int) iovcnt; - } */ a; - struct osf1_iovec *oio; - struct iovec *nio; - - sg = stackgap_init(); - - if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) - return (EINVAL); - - osize = uap->iovcnt * sizeof (struct osf1_iovec); - nsize = uap->iovcnt * sizeof (struct iovec); - - oio = malloc(osize, M_TEMP, M_WAITOK); - nio = malloc(nsize, M_TEMP, M_WAITOK); - - error = 0; - if ((error = copyin(uap->iovp, oio, osize))) - goto punt; - for (i = 0; i < uap->iovcnt; i++) { - nio[i].iov_base = oio[i].iov_base; - nio[i].iov_len = oio[i].iov_len; - } - - a.fd = uap->fd; - a.iovp = stackgap_alloc(&sg, nsize); - a.iovcnt = uap->iovcnt; - - if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) - goto punt; - error = readv(td, &a); + struct uio *auio; + int error; -punt: - free(oio, M_TEMP); - free(nio, M_TEMP); + error = osf1_copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) + return (error); + error = kern_readv(td, uap->fd, auio); + free(auio, M_IOV); return (error); } @@ -1048,46 +1057,14 @@ osf1_writev(td, uap) struct thread *td; struct osf1_writev_args *uap; { - int error, i, nsize, osize; - caddr_t sg; - struct writev_args /* { - syscallarg(int) fd; - syscallarg(struct iovec *) iovp; - syscallarg(u_int) iovcnt; - } */ a; - struct osf1_iovec *oio; - struct iovec *nio; - - sg = stackgap_init(); - - if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) - return (EINVAL); - - osize = uap->iovcnt * sizeof (struct osf1_iovec); - nsize = uap->iovcnt * sizeof (struct iovec); - - oio = malloc(osize, M_TEMP, M_WAITOK); - nio = malloc(nsize, M_TEMP, M_WAITOK); - - error = 0; - if ((error = copyin(uap->iovp, oio, osize))) - goto punt; - for (i = 0; i < uap->iovcnt; i++) { - nio[i].iov_base = oio[i].iov_base; - nio[i].iov_len = oio[i].iov_len; - } - - a.fd = uap->fd; - a.iovp = stackgap_alloc(&sg, nsize); - a.iovcnt = uap->iovcnt; - - if ((error = copyout(nio, (caddr_t)a.iovp, nsize))) - goto punt; - error = writev(td, &a); + struct uio *auio; + int error; -punt: - free(oio, M_TEMP); - free(nio, M_TEMP); + error = osf1_copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) + return (error); + error = kern_writev(td, uap->fd, auio); + free(auio, M_IOV); return (error); } |