summaryrefslogtreecommitdiff
path: root/source3/lib/sendfile.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2002-09-12 02:12:52 +0000
committerJeremy Allison <jra@samba.org>2002-09-12 02:12:52 +0000
commit4f613ac61e9bc442715141188d915b537e15f4c6 (patch)
tree1988e7728bb0828831d953da13db6895c7cc9e13 /source3/lib/sendfile.c
parentb060593287f6344a147da95e5179170335ad78d1 (diff)
downloadsamba-4f613ac61e9bc442715141188d915b537e15f4c6.tar.gz
samba-4f613ac61e9bc442715141188d915b537e15f4c6.tar.bz2
samba-4f613ac61e9bc442715141188d915b537e15f4c6.zip
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)
Diffstat (limited to 'source3/lib/sendfile.c')
-rw-r--r--source3/lib/sendfile.c158
1 files changed, 158 insertions, 0 deletions
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 <sys/sendfile.h>
+
+#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 <sys/socket.h>
+#include <sys/uio.h>
+
+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 <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+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