summaryrefslogtreecommitdiff
path: root/source3/lib/sendfile.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2002-09-30 21:14:46 +0000
committerJeremy Allison <jra@samba.org>2002-09-30 21:14:46 +0000
commit7dc8aa0854b50242d7ac96c674f5c73111b59e29 (patch)
tree5e005590b61402e31efc5563595609a72956ebb2 /source3/lib/sendfile.c
parent834b89cc49dc0be1a7f2b8ed4c6f070cc223896e (diff)
downloadsamba-7dc8aa0854b50242d7ac96c674f5c73111b59e29.tar.gz
samba-7dc8aa0854b50242d7ac96c674f5c73111b59e29.tar.bz2
samba-7dc8aa0854b50242d7ac96c674f5c73111b59e29.zip
Added Solaris sendfile patch + configure tests from Pierre Belanger <belanger@yahoo.com>.
Jeremy. (This used to be commit 8db4d46dc983ce37814fb375d61951b6220a4c61)
Diffstat (limited to 'source3/lib/sendfile.c')
-rw-r--r--source3/lib/sendfile.c87
1 files changed, 84 insertions, 3 deletions
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 <belanger@yahoo.com>.
+ */
+
+#include <sys/sendfile.h>
+
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)