diff options
author | ps <ps@FreeBSD.org> | 2006-02-28 19:39:18 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2006-02-28 19:39:18 +0000 |
commit | 6014145f3878ae927ab23d37d89490e33addf743 (patch) | |
tree | 8d194756dd94e282324cd9c351ff45ebed818cb0 /sys/compat | |
parent | 87272c821ca130738fc0299198dfa74e4ed95086 (diff) | |
download | FreeBSD-src-6014145f3878ae927ab23d37d89490e33addf743.zip FreeBSD-src-6014145f3878ae927ab23d37d89490e33addf743.tar.gz |
Fix 32bit sendfile by implementing kern_sendfile so that it takes
the header and trailers as iovec arguments instead of copying them
in inside of sendfile.
Reviewed by: jhb
MFC after: 3 weeks
Diffstat (limited to 'sys/compat')
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 82 | ||||
-rw-r--r-- | sys/compat/freebsd32/syscalls.master | 4 |
2 files changed, 66 insertions, 20 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 4c00a20..cb05ceb 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -1427,37 +1427,83 @@ freebsd32_ftruncate(struct thread *td, struct freebsd32_ftruncate_args *uap) return (ftruncate(td, &ap)); } -#ifdef COMPAT_FREEBSD4 -int -freebsd4_freebsd32_sendfile(struct thread *td, - struct freebsd4_freebsd32_sendfile_args *uap) +struct sf_hdtr32 { + uint32_t headers; + int hdr_cnt; + uint32_t trailers; + int trl_cnt; +}; + +static int +freebsd32_do_sendfile(struct thread *td, + struct freebsd32_sendfile_args *uap, int compat) { - struct freebsd4_sendfile_args ap; + struct sendfile_args ap; + struct sf_hdtr32 hdtr32; + struct sf_hdtr hdtr; + struct uio *hdr_uio, *trl_uio; + struct iovec32 *iov32; + int error; + + hdr_uio = trl_uio = NULL; ap.fd = uap->fd; ap.s = uap->s; ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); - ap.nbytes = uap->nbytes; /* XXX check */ - ap.hdtr = uap->hdtr; /* XXX check */ - ap.sbytes = uap->sbytes; /* XXX FIXME!! */ + ap.nbytes = uap->nbytes; + ap.hdtr = (struct sf_hdtr *)uap->hdtr; /* XXX not used */ + ap.sbytes = uap->sbytes; ap.flags = uap->flags; - return (freebsd4_sendfile(td, &ap)); + + if (uap->hdtr != NULL) { + error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32)); + if (error) + goto out; + PTRIN_CP(hdtr32, hdtr, headers); + CP(hdtr32, hdtr, hdr_cnt); + PTRIN_CP(hdtr32, hdtr, trailers); + CP(hdtr32, hdtr, trl_cnt); + + if (hdtr.headers != NULL) { + iov32 = (struct iovec32 *)(uintptr_t)hdtr32.headers; + error = freebsd32_copyinuio(iov32, + hdtr32.hdr_cnt, &hdr_uio); + if (error) + goto out; + } + if (hdtr.trailers != NULL) { + iov32 = (struct iovec32 *)(uintptr_t)hdtr32.trailers; + error = freebsd32_copyinuio(iov32, + hdtr32.trl_cnt, &trl_uio); + if (error) + goto out; + } + } + + error = kern_sendfile(td, &ap, hdr_uio, trl_uio, compat); +out: + if (hdr_uio) + free(hdr_uio, M_IOV); + if (trl_uio) + free(trl_uio, M_IOV); + return (error); +} + +#ifdef COMPAT_FREEBSD4 +int +freebsd4_freebsd32_sendfile(struct thread *td, + struct freebsd4_freebsd32_sendfile_args *uap) +{ + return (freebsd32_do_sendfile(td, + (struct freebsd32_sendfile_args *)uap, 1)); } #endif int freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap) { - struct sendfile_args ap; - ap.fd = uap->fd; - ap.s = uap->s; - ap.offset = (uap->offsetlo | ((off_t)uap->offsethi << 32)); - ap.nbytes = uap->nbytes; /* XXX check */ - ap.hdtr = uap->hdtr; /* XXX check */ - ap.sbytes = uap->sbytes; /* XXX FIXME!! */ - ap.flags = uap->flags; - return (sendfile(td, &ap)); + return (freebsd32_do_sendfile(td, uap, 0)); } struct stat32 { diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 05c6a37..d6797c2 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -566,7 +566,7 @@ ; XXX note - bigendian is different 336 AUE_SENDFILE MCOMPAT4 { int freebsd32_sendfile(int fd, int s, \ u_int32_t offsetlo, u_int32_t offsethi, \ - size_t nbytes, struct sf_hdtr *hdtr, \ + size_t nbytes, struct sf_hdtr32 *hdtr, \ off_t *sbytes, int flags); } 337 AUE_NULL MNOPROTO { int kldsym(int fileid, int cmd, \ void *data); } @@ -666,7 +666,7 @@ int count); } 393 AUE_NULL MSTD { int freebsd32_sendfile(int fd, int s, \ u_int32_t offsetlo, u_int32_t offsethi, \ - size_t nbytes, struct sf_hdtr *hdtr, \ + size_t nbytes, struct sf_hdtr32 *hdtr, \ off_t *sbytes, int flags); } 394 AUE_NULL UNIMPL mac_syscall 395 AUE_GETFSSTAT MNOPROTO { int getfsstat(struct statfs *buf, \ |