- Use a custom version of copyinuio() to implement readv/writev using

kern_readv/writev.
- Use kern_settimeofday() and kern_adjtime() rather than stackgapping it.
This commit is contained in:
John Baldwin 2005-03-31 22:58:13 +00:00
parent 3dde27da5e
commit 48052f99e7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=144450

View file

@ -680,99 +680,75 @@ struct iovec32 {
u_int32_t iov_base; u_int32_t iov_base;
int iov_len; int iov_len;
}; };
#define STACKGAPLEN 400
CTASSERT(sizeof(struct iovec32) == 8); CTASSERT(sizeof(struct iovec32) == 8);
static int
freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
{
struct iovec32 iov32;
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], &iov32, sizeof(struct iovec32));
if (error) {
free(uio, M_IOV);
return (error);
}
iov[i].iov_base = PTRIN(iov32.iov_base);
iov[i].iov_len = iov32.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 int
freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap) freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
{ {
int error, osize, nsize, i; struct uio *auio;
caddr_t sg; int error;
struct readv_args /* {
syscallarg(int) fd;
syscallarg(struct iovec *) iovp;
syscallarg(u_int) iovcnt;
} */ a;
struct iovec32 *oio;
struct iovec *nio;
sg = stackgap_init(); error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
if (error)
if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) return (error);
return (EINVAL); error = kern_readv(td, uap->fd, auio);
free(auio, M_IOV);
osize = uap->iovcnt * sizeof (struct iovec32);
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 = PTRIN(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);
punt:
free(oio, M_TEMP);
free(nio, M_TEMP);
return (error); return (error);
} }
int int
freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap) freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
{ {
int error, i, nsize, osize; struct uio *auio;
caddr_t sg; int error;
struct writev_args /* {
syscallarg(int) fd;
syscallarg(struct iovec *) iovp;
syscallarg(u_int) iovcnt;
} */ a;
struct iovec32 *oio;
struct iovec *nio;
sg = stackgap_init(); error = freebsd32_copyinuio(uap->iovp, uap->iovcnt, &auio);
if (error)
if (uap->iovcnt > (STACKGAPLEN / sizeof (struct iovec))) return (error);
return (EINVAL); error = kern_writev(td, uap->fd, auio);
free(auio, M_IOV);
osize = uap->iovcnt * sizeof (struct iovec32);
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 = PTRIN(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);
punt:
free(oio, M_TEMP);
free(nio, M_TEMP);
return (error); return (error);
} }
@ -780,26 +756,28 @@ int
freebsd32_settimeofday(struct thread *td, freebsd32_settimeofday(struct thread *td,
struct freebsd32_settimeofday_args *uap) struct freebsd32_settimeofday_args *uap)
{ {
struct timeval32 tv32;
struct timeval tv, *tvp;
struct timezone tz, *tzp;
int error; int error;
caddr_t sg;
struct timeval32 *p32, s32;
struct timeval *p = NULL, s;
p32 = uap->tv; if (uap->tv) {
if (p32) { error = copyin(uap->tv, &tv32, sizeof(tv32));
sg = stackgap_init();
p = stackgap_alloc(&sg, sizeof(struct timeval));
uap->tv = (struct timeval32 *)p;
error = copyin(p32, &s32, sizeof(s32));
if (error) if (error)
return (error); return (error);
CP(s32, s, tv_sec); CP(tv32, tv, tv_sec);
CP(s32, s, tv_usec); CP(tv32, tv, tv_usec);
error = copyout(&s, p, sizeof(s)); tvp = &tv;
} else
tvp = NULL;
if (uap->tzp) {
error = copyin(uap->tzp, &tz, sizeof(tz));
if (error) if (error)
return (error); return (error);
} tzp = &tz;
return (settimeofday(td, (struct settimeofday_args *) uap)); } else
tzp = NULL;
return (kern_settimeofday(td, tvp, tzp));
} }
int int
@ -826,41 +804,24 @@ freebsd32_utimes(struct thread *td, struct freebsd32_utimes_args *uap)
int int
freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap) freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
{ {
struct timeval32 tv32;
struct timeval delta, olddelta, *deltap;
int error; int error;
caddr_t sg;
struct timeval32 *p32, *op32, s32;
struct timeval *p = NULL, *op = NULL, s;
p32 = uap->delta; if (uap->delta) {
if (p32) { error = copyin(uap->delta, &tv32, sizeof(tv32));
sg = stackgap_init();
p = stackgap_alloc(&sg, sizeof(struct timeval));
uap->delta = (struct timeval32 *)p;
error = copyin(p32, &s32, sizeof(s32));
if (error) if (error)
return (error); return (error);
CP(s32, s, tv_sec); CP(tv32, delta, tv_sec);
CP(s32, s, tv_usec); CP(tv32, delta, tv_usec);
error = copyout(&s, p, sizeof(s)); deltap = &delta;
if (error) } else
return (error); deltap = NULL;
} error = kern_adjtime(td, deltap, &olddelta);
op32 = uap->olddelta; if (uap->olddelta && error == 0) {
if (op32) { CP(olddelta, tv32, tv_sec);
sg = stackgap_init(); CP(olddelta, tv32, tv_usec);
op = stackgap_alloc(&sg, sizeof(struct timeval)); error = copyout(&tv32, uap->olddelta, sizeof(tv32));
uap->olddelta = (struct timeval32 *)op;
}
error = adjtime(td, (struct adjtime_args *) uap);
if (error)
return error;
if (op32) {
error = copyin(op, &s, sizeof(s));
if (error)
return (error);
CP(s, s32, tv_sec);
CP(s, s32, tv_usec);
error = copyout(&s32, op32, sizeof(s32));
} }
return (error); return (error);
} }