summaryrefslogtreecommitdiffstats
path: root/sys/alpha/osf1
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2005-03-31 22:56:14 +0000
committerjhb <jhb@FreeBSD.org>2005-03-31 22:56:14 +0000
commita9a1057e5e88beb273b050d301ed4b315a6fbc5f (patch)
treeb293ea5b89d830b18d6e272eb20392c21add3a54 /sys/alpha/osf1
parent76cb101294622496d32b4a3b91c71aa3fb9e5e01 (diff)
downloadFreeBSD-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/osf1')
-rw-r--r--sys/alpha/osf1/osf1_misc.c135
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);
}
OpenPOWER on IntegriCloud