summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2006-02-28 19:39:18 +0000
committerps <ps@FreeBSD.org>2006-02-28 19:39:18 +0000
commit6014145f3878ae927ab23d37d89490e33addf743 (patch)
tree8d194756dd94e282324cd9c351ff45ebed818cb0 /sys/compat
parent87272c821ca130738fc0299198dfa74e4ed95086 (diff)
downloadFreeBSD-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.c82
-rw-r--r--sys/compat/freebsd32/syscalls.master4
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, \
OpenPOWER on IntegriCloud