From 4f613ac61e9bc442715141188d915b537e15f4c6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Sep 2002 02:12:52 +0000 Subject: First cut at portable sendfile code. Only used in readX at the moment and doesn't actually call sendfile. Needs to be vectored through the VFS and tested on all supported platforms (Solaris/HPUX/FreeBSD/Linux). Linux doesn't actually work (2.4.19 kernel) at the moment because it doesn't have a 64-bit clean sendfile. Jeremy. (This used to be commit fd772ca7b16cd86e0d50c7ed8d537c202976a6d2) --- source3/lib/sendfile.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 source3/lib/sendfile.c (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c new file mode 100644 index 0000000000..33282e704a --- /dev/null +++ b/source3/lib/sendfile.c @@ -0,0 +1,158 @@ +/* + Unix SMB/Netbios implementation. + Version 2.2.x / 3.0.x + sendfile implementations. + Copyright (C) Jeremy Allison 2002. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* + * This file handles the OS dependent sendfile implementations. + * The API is such that it returns -1 on error, else returns the + * number of bytes written. + */ + +#include "includes.h" + +#if defined(LINUX_SENDFILE_API) + +#include + +#ifndef MSG_MORE +#define MSG_MORE 0x8000 +#endif + +ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + ssize_t ret; + + /* + * Send the header first. + * Use MSG_MORE to cork the TCP output until sendfile is called. + */ + + while (total < header->length) { + ret = sys_send(outfd, header->data + total,header->length - total, MSG_MORE); + if (ret == -1) + return -1; + total += ret; + } + + total = count; + while (total) { + ssize_t nwritten; + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) + nwritten = sendfile64(outfd, infd, &offset, total); +#else + nwritten = sendfile(outfd, infd, &offset, total); +#endif + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + total -= nwritten; + } + return count + header->length; +} + +#elif defined(SOLARIS_SENDFILE_API) + +ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ +} + +#elif defined(HPUX_SENDFILE_API) + +#include +#include + +ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + struct iovec hdtrl[2]; + + /* Set up the header/trailer iovec. */ + hdtrl[0].iov_base = header->data; + hdtrl[0].iov_len = header->length; + hdtrl[1].iov_base = NULL; + hdtrl[1].iov_base = 0; + + total = count; + while (total) { + ssize_t nwritten; + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) + nwritten = sendfile64(outfd, infd, &offset, total, &hdtrl, 0); +#else + nwritten = sendfile(outfd, infd, &offset, total, &hdtrl, 0); +#endif + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + total -= nwritten; + } + return count + header->length; +} + +#elif defined(FREEBSD_SENDFILE_API) + +#include +#include +#include + +ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + struct sf_hdtr hdr; + struct iovec hdtrl; + + hdr->headers = &hdtrl; + hdr->hdr_cnt = 1; + hdr->trailers = NULL; + hdr->trl_cnt = 0; + + /* Set up the header iovec. */ + hdtrl.iov_base = header->data; + hdtrl.iov_len = header->length; + + total = count; + while (total) { + ssize_t nwritten; + do { +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) + nwritten = sendfile64(outfd, infd, &offset, total, &hdr, NULL, 0); +#else + nwritten = sendfile(outfd, infd, &offset, total, &hdr, NULL, 0); +#endif + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + total -= nwritten; + } + return count + header->length; +} + +#else /* No sendfile implementation. Return error. */ + +ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + /* No sendfile syscall. */ + errno = ENOSYS; + return -1; +} +#endif -- cgit From fdb8c4dfe1d367deda6d0183d94f44d5d5e14992 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Sep 2002 06:24:41 +0000 Subject: Fixup sendfile to match HPUX semantics with signal interrups. This was fiddly.... :-(. Jeremy. (This used to be commit 2b33a500a8ad13acdd7e4f593aba65229dc8dd96) --- source3/lib/sendfile.c | 64 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 12 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 33282e704a..11bf38ebee 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -38,17 +38,21 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off { size_t total=0; ssize_t ret; + ssize_t hdr_len = 0; /* * Send the header first. * Use MSG_MORE to cork the TCP output until sendfile is called. */ - while (total < header->length) { - ret = sys_send(outfd, header->data + total,header->length - total, MSG_MORE); - if (ret == -1) - return -1; - total += ret; + if (header) { + hdr_len = header->length; + while (total < hd_len) { + ret = sys_send(outfd, header->data + total,hdr_len - total, MSG_MORE); + if (ret == -1) + return -1; + total += ret; + } } total = count; @@ -67,7 +71,7 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off return -1; /* I think we're at EOF here... */ total -= nwritten; } - return count + header->length; + return count + hdr_len; } #elif defined(SOLARIS_SENDFILE_API) @@ -85,16 +89,30 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off { size_t total=0; struct iovec hdtrl[2]; - - /* Set up the header/trailer iovec. */ - hdtrl[0].iov_base = header->data; - hdtrl[0].iov_len = header->length; + size_t hdr_len = 0; + + if (header) { + /* Set up the header/trailer iovec. */ + hdtrl[0].iov_base = header->data; + hdtrl[0].iov_len = hdr_len = header->length; + } else { + hdtrl[0].iov_base = NULL; + hdtrl[0].iov_len = hdr_len = 0; + } hdtrl[1].iov_base = NULL; hdtrl[1].iov_base = 0; total = count; - while (total) { + while (total + hdtrl[0].iov_len) { ssize_t nwritten; + + /* + * HPUX guarantees that if any data was written before + * a signal interrupt then sendfile returns the number of + * bytes written (which may be less than requested) not -1. + * nwritten includes the header data sent. + */ + do { #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) nwritten = sendfile64(outfd, infd, &offset, total, &hdtrl, 0); @@ -104,9 +122,31 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off } while (nwritten == -1 && errno == EINTR); if (nwritten == -1) return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than hdtrl[0].iov_len bytes. + * We change nwritten to be the number of file bytes written. + */ + + if (hdtrl[0].iov_base && hdtrl[0].iov_len) { + if (nwritten >= hdtrl[0].iov_len) { + nwritten -= hdtrl[0].iov_len; + hdtrl[0].iov_base = NULL; + hdtrl[0].iov_len = 0; + } else { + nwritten = 0; + hdtrl[0].iov_base += nwritten; + hdtrl[0].iov_len -= nwritten; + } + } total -= nwritten; + offset += nwritten; } - return count + header->length; + return count + hdr_len; } #elif defined(FREEBSD_SENDFILE_API) -- cgit From 8c5f577c6f40de2f346b4545cbcdfb08e30f629f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Sep 2002 06:26:06 +0000 Subject: HPUX takes offset, not pointer to offset. Jeremy. (This used to be commit d7024e8cb94a20cba789deb2c5b70221f6cca4fd) --- source3/lib/sendfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 11bf38ebee..23d1154718 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -115,9 +115,9 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off do { #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) - nwritten = sendfile64(outfd, infd, &offset, total, &hdtrl, 0); + nwritten = sendfile64(outfd, infd, offset, total, &hdtrl[0], 0); #else - nwritten = sendfile(outfd, infd, &offset, total, &hdtrl, 0); + nwritten = sendfile(outfd, infd, offset, total, &hdtrl[0], 0); #endif } while (nwritten == -1 && errno == EINTR); if (nwritten == -1) -- cgit From 6cf499ecff96880acef4e53817dccd7d838edd62 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Sep 2002 18:18:35 +0000 Subject: Fixed up FreeBSD sendfile code - only Solaris left then I can add the configure tests... Jeremy. (This used to be commit 9dad88e1d4d09f61da87dab2633c6e989a9dd77f) --- source3/lib/sendfile.c | 77 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 22 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 23d1154718..6e093c31ff 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -34,7 +34,7 @@ #define MSG_MORE 0x8000 #endif -ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { size_t total=0; ssize_t ret; @@ -48,7 +48,7 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off if (header) { hdr_len = header->length; while (total < hd_len) { - ret = sys_send(outfd, header->data + total,hdr_len - total, MSG_MORE); + ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); if (ret == -1) return -1; total += ret; @@ -60,9 +60,9 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off ssize_t nwritten; do { #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) - nwritten = sendfile64(outfd, infd, &offset, total); + nwritten = sendfile64(tofd, fromfd, &offset, total); #else - nwritten = sendfile(outfd, infd, &offset, total); + nwritten = sendfile(tofd, fromfd, &offset, total); #endif } while (nwritten == -1 && errno == EINTR); if (nwritten == -1) @@ -76,7 +76,7 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off #elif defined(SOLARIS_SENDFILE_API) -ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { } @@ -85,7 +85,7 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off #include #include -ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { size_t total=0; struct iovec hdtrl[2]; @@ -115,9 +115,9 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off do { #if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) - nwritten = sendfile64(outfd, infd, offset, total, &hdtrl[0], 0); + nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0); #else - nwritten = sendfile(outfd, infd, offset, total, &hdtrl[0], 0); + nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0); #endif } while (nwritten == -1 && errno == EINTR); if (nwritten == -1) @@ -155,11 +155,12 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off #include #include -ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { size_t total=0; struct sf_hdtr hdr; struct iovec hdtrl; + size_t hdr_len = 0; hdr->headers = &hdtrl; hdr->hdr_cnt = 1; @@ -167,29 +168,61 @@ ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T off hdr->trl_cnt = 0; /* Set up the header iovec. */ - hdtrl.iov_base = header->data; - hdtrl.iov_len = header->length; + if (header) { + hdtrl.iov_base = header->data; + hdtrl.iov_len = hdr_len = header->length; + } else { + hdtrl.iov_base = NULL; + hdtrl.iov_len = 0; + } total = count; - while (total) { - ssize_t nwritten; + while (total + hdtrl.iov_len) { + SMB_OFF_T nwritten; + int ret; + + /* + * FreeBSD sendfile returns 0 on success, -1 on error. + * Remember, the tofd and fromfd are reversed..... :-). + * nwritten includes the header data sent. + */ + do { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) - nwritten = sendfile64(outfd, infd, &offset, total, &hdr, NULL, 0); -#else - nwritten = sendfile(outfd, infd, &offset, total, &hdr, NULL, 0); -#endif - } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) + ret = sendfile(fromfd, tofd, offset, total, &hdr, &nwritten, 0); + } while (ret == -1 && errno == EINTR); + if (ret == -1) return -1; + + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than hdtrl.iov_len bytes. + * We change nwritten to be the number of file bytes written. + */ + + if (hdtrl[0].iov_base && hdtrl.iov_len) { + if (nwritten >= hdtrl.iov_len) { + nwritten -= hdtrl.iov_len; + hdtrl.iov_base = NULL; + hdtrl.iov_len = 0; + } else { + nwritten = 0; + hdtrl.iov_base += nwritten; + hdtrl.iov_len -= nwritten; + } + } total -= nwritten; + offset += nwritten; } - return count + header->length; + return count + hdr_len; } #else /* No sendfile implementation. Return error. */ -ssize_t sys_sendfile(int outfd, int infd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { /* No sendfile syscall. */ errno = ENOSYS; -- cgit From febd3f929b0f922a4bac69aa131089da4675cb1e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Sep 2002 00:34:46 +0000 Subject: Added fix for broken Linux (no sendfile64). When offset + count > 2GB then return ENOSYS and let the upper layer handle it. Jeremy (This used to be commit 872dfd87cda585c33c3823b06580cb301567a9b9) --- source3/lib/sendfile.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 6e093c31ff..2707495d5b 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -74,6 +74,63 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of return count + hdr_len; } +#elif defined(LINUX_BROKEN_SENDFILE_API) + +#include + +#ifndef MSG_MORE +#define MSG_MORE 0x8000 +#endif + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + ssize_t ret; + ssize_t hdr_len = 0; + + /* + * Fix for broken Linux 2.4 systems with no working sendfile64(). + * If the offset+count > 2 GB then pretend we don't have the + * system call sendfile at all. The upper later catches this + * and uses a normal read. JRA. + */ + + if ((sizeof(SMB_OFF_T) >= 8) && (offset + count > (SMB_OFF_T)0x7FFFFFFF)) { + errno = ENOSYS; + return -1; + } + + /* + * Send the header first. + * Use MSG_MORE to cork the TCP output until sendfile is called. + */ + + if (header) { + hdr_len = header->length; + while (total < hd_len) { + ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); + if (ret == -1) + return -1; + total += ret; + } + } + + total = count; + while (total) { + ssize_t nwritten; + do { + nwritten = sendfile(tofd, fromfd, &offset, total); + } while (nwritten == -1 && errno == EINTR); + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + total -= nwritten; + } + return count + hdr_len; +} + + #elif defined(SOLARIS_SENDFILE_API) ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -- cgit From 3f02393bfd49dea3f48fdb759d8f932d5bb3a8f6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 14 Sep 2002 01:38:55 +0000 Subject: Use HAVE_SENDFILE64, not SENDFILE64. Jeremy. (This used to be commit 7e2f9769c9a7ee5d11267a8a8864371fc0aa8f50) --- source3/lib/sendfile.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 2707495d5b..4613cfb864 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -59,7 +59,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of while (total) { ssize_t nwritten; do { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64) nwritten = sendfile64(tofd, fromfd, &offset, total); #else nwritten = sendfile(tofd, fromfd, &offset, total); @@ -133,8 +133,11 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of #elif defined(SOLARIS_SENDFILE_API) +/* Hmmm. Can't find Solaris sendfile API docs.... Where is it ? */ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { + errno = ENOSYS; + return -1; } #elif defined(HPUX_SENDFILE_API) @@ -171,7 +174,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of */ do { -#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(SENDFILE64) +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64) nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0); #else nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0); -- cgit From f74086ccf09e8157419f7c51490dc31effb6ba20 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Sep 2002 01:00:03 +0000 Subject: Attempt to make broken Linux sendfile work.... Still in progress. Jeremy. (This used to be commit f956a4d29d0d88cd92fac0f0c9f636fc152afe0a) --- source3/lib/sendfile.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 4613cfb864..8bcb9dbd02 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -76,7 +76,13 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of #elif defined(LINUX_BROKEN_SENDFILE_API) -#include +/* + * We must use explicit 32 bit types here. This code path means Linux + * won't do proper 64-bit sendfile. JRA. + */ + +extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count); + #ifndef MSG_MORE #define MSG_MORE 0x8000 @@ -87,11 +93,13 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of size_t total=0; ssize_t ret; ssize_t hdr_len = 0; + uint32 small_total = 0; + int32 small_offset; /* * Fix for broken Linux 2.4 systems with no working sendfile64(). * If the offset+count > 2 GB then pretend we don't have the - * system call sendfile at all. The upper later catches this + * system call sendfile at all. The upper layer catches this * and uses a normal read. JRA. */ @@ -115,17 +123,19 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of } } - total = count; - while (total) { - ssize_t nwritten; + small_total = (uint32)count; + small_offset = (int32)offset; + + while (small_total) { + int32 nwritten; do { - nwritten = sendfile(tofd, fromfd, &offset, total); + nwritten = sendfile(tofd, fromfd, &small_offset, small_total); } while (nwritten == -1 && errno == EINTR); if (nwritten == -1) return -1; if (nwritten == 0) return -1; /* I think we're at EOF here... */ - total -= nwritten; + small_total -= nwritten; } return count + hdr_len; } -- cgit From 9bab1d0c1a51a7532da0c55a59cf5a91b8ab6a3d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Sep 2002 19:48:19 +0000 Subject: Actually use sendfile if selected. Jeremy. (This used to be commit 5881f0a22633ed9fb73e6cd788d0751c4db6cd32) --- source3/lib/sendfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 8bcb9dbd02..bcace5fee2 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -47,7 +47,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of if (header) { hdr_len = header->length; - while (total < hd_len) { + while (total < hdr_len) { ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); if (ret == -1) return -1; @@ -115,7 +115,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of if (header) { hdr_len = header->length; - while (total < hd_len) { + while (total < hdr_len) { ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE); if (ret == -1) return -1; -- cgit From 994638f577d2d0df8f5f185fd96d4448dcd9d7e5 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Sep 2002 20:07:56 +0000 Subject: HPUX sendfile is now detected correctly. Jeremy. (This used to be commit 91e41ebe97c143f413e2a5614b20f3db4642490f) --- source3/lib/sendfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index bcace5fee2..df6c1980d0 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -209,7 +209,8 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of hdtrl[0].iov_len = 0; } else { nwritten = 0; - hdtrl[0].iov_base += nwritten; + /* iov_base is defined as a void *... */ + hdtrl[0].iov_base = ((char *)hdtrl[0].iov_base) + nwritten; hdtrl[0].iov_len -= nwritten; } } -- cgit From 515c1d42eec8d7c0a5eabeb72b274f5446012945 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 21 Sep 2002 08:53:05 +0000 Subject: Merge back Richard's FreeBSD sendfile fixes. Jeremy. (This used to be commit f4845b0213aec58e0f489eba5653aa7b3855610f) --- source3/lib/sendfile.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index df6c1980d0..98a52608b8 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -233,10 +233,10 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of struct iovec hdtrl; size_t hdr_len = 0; - hdr->headers = &hdtrl; - hdr->hdr_cnt = 1; - hdr->trailers = NULL; - hdr->trl_cnt = 0; + hdr.headers = &hdtrl; + hdr.hdr_cnt = 1; + hdr.trailers = NULL; + hdr.trl_cnt = 0; /* Set up the header iovec. */ if (header) { @@ -274,7 +274,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of * We change nwritten to be the number of file bytes written. */ - if (hdtrl[0].iov_base && hdtrl.iov_len) { + if (hdtrl.iov_base && hdtrl.iov_len) { if (nwritten >= hdtrl.iov_len) { nwritten -= hdtrl.iov_len; hdtrl.iov_base = NULL; -- cgit From f6bdffbf8dfc28329e87fcc383008c685110db96 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Sep 2002 05:24:12 +0000 Subject: Don't zero out numwritten before using.... Found by Pierre Belanger belanger@pobox.com Jeremy. (This used to be commit 495e6e3287152a7ec218a38b3133f7ae16d5a8d1) --- source3/lib/sendfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 98a52608b8..5d1cf2f10b 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -208,10 +208,10 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of hdtrl[0].iov_base = NULL; hdtrl[0].iov_len = 0; } else { - nwritten = 0; /* iov_base is defined as a void *... */ hdtrl[0].iov_base = ((char *)hdtrl[0].iov_base) + nwritten; hdtrl[0].iov_len -= nwritten; + nwritten = 0; } } total -= nwritten; @@ -280,9 +280,9 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of hdtrl.iov_base = NULL; hdtrl.iov_len = 0; } else { - nwritten = 0; hdtrl.iov_base += nwritten; hdtrl.iov_len -= nwritten; + nwritten = 0; } } total -= nwritten; -- cgit From 4d2d5c4ace09a74420b74f1b9fbee04ecf5fa08b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 30 Sep 2002 21:17:18 +0000 Subject: Added Solaris sendfile patch + configure tests from Pierre Belanger . Jeremy. (This used to be commit 9c17faefa5cb0ed450578ae5bbcca44e3058bc9b) --- source3/lib/sendfile.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 3 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 5d1cf2f10b..d2ecf3f94a 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -143,11 +143,92 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of #elif defined(SOLARIS_SENDFILE_API) -/* Hmmm. Can't find Solaris sendfile API docs.... Where is it ? */ +/* + * Solaris sendfile code written by Pierre Belanger . + */ + +#include + ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { - errno = ENOSYS; - return -1; + int sfvcnt; + size_t total, xferred; + struct sendfilevec vec[2]; + ssize_t hdr_len = 0; + + if (header) { + sfvcnt = 2; + + vec[0].sfv_fd = SFV_FD_SELF; + vec[0].sfv_flag = 0; + vec[0].sfv_off = header->data; + vec[0].sfv_len = header->length; + + vec[1].sfv_fd = fromfd; + vec[1].sfv_flag = 0; + vec[1].sfv_off = offset; + vec[1].sfv_len = count; + + hdr_len = header->length; + } else { + sfvcnt = 1; + + vec[0].sfv_fd = fromfd; + vec[0].sfv_flag = 0; + vec[0].sfv_off = offset; + vec[0].sfv_len = count; + } + + total = count + hdr_len; + + while (total) { + ssize_t nwritten; + + /* + * Although not listed in the API error returns, this is almost certainly + * a slow system call and will be interrupted by a signal with EINTR. JRA. + */ + + xferred = 0; + +#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILEV64) + nwritten = sendfilev64(tofd, vec, sfvcnt, &xferred); +#else + nwritten = sendfilev(tofd, vec, sfvcnt, &xferred); +#endif + if (nwritten == -1 && errno == EINTR) { + if (xferred == 0) + continue; /* Nothing written yet. */ + else + nwritten = xferred; + } + + if (nwritten == -1) + return -1; + if (nwritten == 0) + return -1; /* I think we're at EOF here... */ + + /* + * If this was a short (signal interrupted) write we may need + * to subtract it from the header data, or null out the header + * data altogether if we wrote more than vec[0].sfv_len bytes. + * We move vec[1].* to vec[0].* and set sfvcnt to 1 + */ + + if (sfvcnt == 2 && nwritten >= vec[0].sfv_len) { + vec[1].sfv_off += nwritten - vec[0].sfv_len; + vec[1].sfv_len -= nwritten - vec[0].sfv_len; + + /* Move vec[1].* to vec[0].* and set sfvcnt to 1 */ + vec[0] = vec[1]; + sfvcnt = 1; + } else { + vec[0].sfv_off += nwritten; + vec[0].sfv_len -= nwritten; + } + total -= nwritten; + } + return count + hdr_len; } #elif defined(HPUX_SENDFILE_API) -- cgit From 88e481ec13505f7e870a2172db3d4edf5ce47caf Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 1 Oct 2002 05:54:40 +0000 Subject: Fix Solaris sendfile detection. Add small fixes to sendfile code. Jeremy. (This used to be commit 7ba5636897ea57669c62d22bb399bcfe5e3a9907) --- source3/lib/sendfile.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index d2ecf3f94a..ccebd25cc1 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -144,7 +144,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of #elif defined(SOLARIS_SENDFILE_API) /* - * Solaris sendfile code written by Pierre Belanger . + * Solaris sendfile code written by Pierre Belanger . */ #include @@ -162,14 +162,13 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of vec[0].sfv_fd = SFV_FD_SELF; vec[0].sfv_flag = 0; vec[0].sfv_off = header->data; - vec[0].sfv_len = header->length; + vec[0].sfv_len = hdr_len = header->length; vec[1].sfv_fd = fromfd; vec[1].sfv_flag = 0; vec[1].sfv_off = offset; vec[1].sfv_len = count; - hdr_len = header->length; } else { sfvcnt = 1; -- cgit From 48f6ede4b4170522cf6f8b19921f10c3f89150c8 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Fri, 24 Jan 2003 16:34:54 +0000 Subject: merging [un]signed declaration (This used to be commit 15be89e72fee97106db1bd06d18060c21bbf78e1) --- source3/lib/sendfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index ccebd25cc1..bcc8cb08ca 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -38,7 +38,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of { size_t total=0; ssize_t ret; - ssize_t hdr_len = 0; + size_t hdr_len = 0; /* * Send the header first. -- cgit From 0dd2e07ea555366c71507c6252254269ce2a558f Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Sun, 2 Nov 2003 13:59:37 +0000 Subject: Cast to fix warning on Solaris sendfile - check buildfarm output to see if this works! Bug #706. (This used to be commit 67ab91825db9b81b8b4f35e86a7eede0c7df5621) --- source3/lib/sendfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index bcc8cb08ca..4aa76a0c74 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -161,7 +161,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of vec[0].sfv_fd = SFV_FD_SELF; vec[0].sfv_flag = 0; - vec[0].sfv_off = header->data; + vec[0].sfv_off = (off_t)header->data; vec[0].sfv_len = hdr_len = header->length; vec[1].sfv_fd = fromfd; -- cgit From 314ec086f3a015f97cc5dafc3038b3bf782d92af Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 24 Nov 2004 22:05:59 +0000 Subject: r3944: Fix the problem we get on Linux where sendfile fails, but we've already sent the header using send(). As our implementation of sendfile can't return EINTR (it restarts in that case) use an errno of EINTR to signal the linux sendfile fail after header case. When that happens send the rest of the data and then turn off sendfile. Sendfile should be safe to enable on all systems now (even though it may not help in all performance cases). Jeremy. (This used to be commit 78236382f7ffe08d7924907be49493779521837f) --- source3/lib/sendfile.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 4aa76a0c74..75fb635fa2 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -65,8 +65,20 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of nwritten = sendfile(tofd, fromfd, &offset, total); #endif } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) + if (nwritten == -1) { + if (errno == ENOSYS) { + /* Ok - we're in a world of pain here. We just sent + * the header, but the sendfile failed. We have to + * emulate the sendfile at an upper layer before we + * disable it's use. So we do something really ugly. + * We set the errno to a strange value so we can detect + * this at the upper level and take care of it without + * layer violation. JRA. + */ + errno = EINTR; /* Normally we can never return this. */ + } return -1; + } if (nwritten == 0) return -1; /* I think we're at EOF here... */ total -= nwritten; @@ -131,8 +143,20 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of do { nwritten = sendfile(tofd, fromfd, &small_offset, small_total); } while (nwritten == -1 && errno == EINTR); - if (nwritten == -1) + if (nwritten == -1) { + if (errno == ENOSYS) { + /* Ok - we're in a world of pain here. We just sent + * the header, but the sendfile failed. We have to + * emulate the sendfile at an upper layer before we + * disable it's use. So we do something really ugly. + * We set the errno to a strange value so we can detect + * this at the upper level and take care of it without + * layer violation. JRA. + */ + errno = EINTR; /* Normally we can never return this. */ + } return -1; + } if (nwritten == 0) return -1; /* I think we're at EOF here... */ small_total -= nwritten; -- cgit From be60bf64478261a642b5636669c7a8fc92b7b13d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 20 Dec 2004 22:33:37 +0000 Subject: r4296: Patch from William Jojo to fix HPUX sendfile and add configure.in tests and code for sendfile on AIX. Jeremy. (This used to be commit f08aceb9882fb1df1e1e28179f87ac5c3d5afa45) --- source3/lib/sendfile.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 75fb635fa2..f9f33b8f35 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -274,7 +274,7 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of hdtrl[0].iov_len = hdr_len = 0; } hdtrl[1].iov_base = NULL; - hdtrl[1].iov_base = 0; + hdtrl[1].iov_len = 0; total = count; while (total + hdtrl[0].iov_len) { @@ -395,6 +395,62 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of return count + hdr_len; } +#elif defined(AIX_SENDFILE_API) + +/* BEGIN AIX SEND_FILE */ + +/* Contributed by William Jojo */ +#include + +ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) +{ + size_t total=0; + struct sf_parms hdtrl; + + /* Set up the header/trailer struct params. */ + if (header) { + hdtrl.header_data = header->data; + hdtrl.header_length = header->length; + } else { + hdtrl.header_data = NULL; + hdtrl.header_length = 0; + } + hdtrl.trailer_data = NULL; + hdtrl.trailer_length = 0; + + hdtrl.file_descriptor = fromfd; + hdtrl.file_offset = offset; + hdtrl.file_bytes = count; + + while ( hdtrl.file_bytes + hdtrl.header_length ) { + ssize_t ret; + + /* + Return Value + + There are three possible return values from send_file: + + Value Description + + -1 an error has occurred, errno contains the error code. + + 0 the command has completed successfully. + + 1 the command was completed partially, some data has been + transmitted but the command has to return for some reason, + for example, the command was interrupted by signals. + */ + do { + ret = send_file(&tofd, &hdtrl, 0); + } while ( (ret == 1) || (ret == -1 && errno == EINTR) ); + if ( ret == -1 ) + return -1; + } + + return count + header->length; +} +/* END AIX SEND_FILE */ + #else /* No sendfile implementation. Return error. */ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) -- cgit From a1c56e451f7c4d6503330bed01a82312b0000f7b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Mar 2006 20:07:36 +0000 Subject: r14393: Fix a couple of AIX warnings. Jeremy. (This used to be commit 8444c997bd3e18b1d04ebe85f06c8c6e34d7373f) --- source3/lib/sendfile.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index f9f33b8f35..f4f6e16526 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -404,7 +404,6 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count) { - size_t total=0; struct sf_parms hdtrl; /* Set up the header/trailer struct params. */ -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/lib/sendfile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index f4f6e16526..46099efd8f 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -6,7 +6,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -- cgit From 153cfb9c83534b09f15cc16205d7adb19b394928 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 05:23:25 +0000 Subject: r23801: The FSF has moved around a lot. This fixes their Mass Ave address. (This used to be commit 87c91e4362c51819032bfbebbb273c52e203b227) --- source3/lib/sendfile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 46099efd8f..20b2371273 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -14,8 +14,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program; if not, see . */ /* -- cgit From 06d0790c0799112b89534a646e78d0cb38b06e20 Mon Sep 17 00:00:00 2001 From: Zach Loafman Date: Thu, 3 Jul 2008 22:53:42 -0700 Subject: Fix various build warnings This fixes various build warnings on our platform. I'm sure I haven't caught them all, but it's a start. (This used to be commit 6b73f259cb67d9dda9127907d706f9244a871fa3) --- source3/lib/sendfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/lib/sendfile.c') diff --git a/source3/lib/sendfile.c b/source3/lib/sendfile.c index 20b2371273..d1b178577c 100644 --- a/source3/lib/sendfile.c +++ b/source3/lib/sendfile.c @@ -383,7 +383,8 @@ ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T of hdtrl.iov_base = NULL; hdtrl.iov_len = 0; } else { - hdtrl.iov_base += nwritten; + hdtrl.iov_base = + (caddr_t)hdtrl.iov_base + nwritten; hdtrl.iov_len -= nwritten; nwritten = 0; } -- cgit