changeset 58:8aaa39e7aec8 HEAD

sendfile() works now properly with 64bit off_t
author Timo Sirainen <tss@iki.fi>
date Wed, 28 Aug 2002 03:11:51 +0300
parents 2d2e2594e60f
children 296c6dbf50a5
files src/lib/Makefile.am src/lib/iobuffer.c src/lib/sendfile-util.c src/lib/sendfile-util.h
diffstat 4 files changed, 68 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib/Makefile.am	Wed Aug 28 03:11:32 2002 +0300
+++ b/src/lib/Makefile.am	Wed Aug 28 03:11:51 2002 +0300
@@ -34,6 +34,7 @@
 	primes.c \
 	randgen.c \
 	restrict-access.c \
+	sendfile-util.c \
 	strfuncs.c \
 	temp-mempool.c \
 	temp-string.c \
@@ -64,6 +65,7 @@
 	primes.h \
 	randgen.h \
 	restrict-access.h \
+	sendfile-util.h \
 	strfuncs.h \
 	temp-mempool.h \
 	temp-string.h \
--- a/src/lib/iobuffer.c	Wed Aug 28 03:11:32 2002 +0300
+++ b/src/lib/iobuffer.c	Wed Aug 28 03:11:51 2002 +0300
@@ -27,14 +27,11 @@
 #include "ioloop.h"
 #include "iobuffer.h"
 #include "mmap-util.h"
+#include "sendfile-util.h"
 #include "network.h"
 
 #include <unistd.h>
 
-#ifdef HAVE_SYS_SENDFILE_H
-#  include <sys/sendfile.h>
-#endif
-
 static unsigned int mmap_pagesize = 0;
 static unsigned int mmap_pagemask = 0;
 
@@ -454,18 +451,14 @@
         return 1;
 }
 
-#ifdef HAVE_SYS_SENDFILE_H
 static void block_loop_sendfile(IOBufferBlockContext *ctx)
 {
-	off_t offset;
 	int ret;
 
 	i_assert(ctx->inbuf->offset < OFF_T_MAX);
 
-	offset = (off_t)ctx->inbuf->offset;
-	ret = sendfile(ctx->outbuf->fd, ctx->inbuf->fd, &offset, ctx->size);
-	ctx->inbuf->offset = (uoff_t)offset;
-
+	ret = safe_sendfile(ctx->outbuf->fd, ctx->inbuf->fd,
+			    &ctx->inbuf->offset, ctx->size);
 	if (ret < 0) {
 		if (errno != EINTR && errno != EAGAIN)
 			ctx->outbuf->closed = TRUE;
@@ -481,7 +474,6 @@
 			      unsigned int size)
 {
         IOBufferBlockContext ctx;
-	off_t offset;
 	int ret;
 
 	i_assert(inbuf->offset < OFF_T_MAX);
@@ -489,10 +481,7 @@
 	io_buffer_send_flush(outbuf);
 
 	/* first try if we can do it with a single sendfile() call */
-	offset = (off_t)inbuf->offset;
-	ret = sendfile(outbuf->fd, inbuf->fd, &offset, size);
-	inbuf->offset = (uoff_t)offset;
-
+	ret = safe_sendfile(outbuf->fd, inbuf->fd, &inbuf->offset, size);
 	if (ret < 0) {
 		if (errno != EINTR && errno != EAGAIN)
 			return -1;
@@ -517,7 +506,6 @@
 	}
 	return ret;
 }
-#endif
 
 static void block_loop_copy(IOBufferBlockContext *ctx)
 {
@@ -551,14 +539,13 @@
 
 	i_assert(size < INT_MAX);
 
-#ifdef HAVE_SYS_SENDFILE_H
 	ret = io_buffer_sendfile(outbuf, inbuf, size);
 	if (ret >= 0 || errno != EINVAL)
 		return ret;
 
-	/* sendfile() not supported with fd, fallback to
+	/* sendfile() not supported (with this fd), fallback to
 	   regular sending */
-#endif
+
 	/* see if we can do it at one go */
 	ret = io_buffer_read_data(inbuf, &in_data, &in_size, 0);
 	if (ret == -1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/sendfile-util.c	Wed Aug 28 03:11:51 2002 +0300
@@ -0,0 +1,53 @@
+/* kludge a bit to remove _FILE_OFFSET_BITS definition from config.h.
+   It's required to be able to include sys/sendfile.h with Linux. */
+#include "../../config.h"
+#undef HAVE_CONFIG_H
+#undef _FILE_OFFSET_BITS
+
+#include "lib.h"
+#include "sendfile-util.h"
+
+#ifdef HAVE_SYS_SENDFILE_H
+
+#include <sys/sendfile.h>
+
+ssize_t safe_sendfile(int out_fd, int in_fd, uoff_t *offset, size_t count)
+{
+	/* REMEBER: uoff_t and off_t may not be of same size. */
+	off_t safe_offset;
+	ssize_t ret;
+
+	/* make sure given offset fits into off_t */
+	if (sizeof(off_t) * CHAR_BIT == 32) {
+		/* 32bit off_t */
+		if (*offset > 2147483647L) {
+			errno = EINVAL;
+			return -1;
+		}
+	} else {
+		/* they're most likely the same size. if not, fix this
+		   code later */
+		i_assert(sizeof(off_t) == sizeof(uoff_t));
+
+		if (*offset > OFF_T_MAX) {
+			errno = EINVAL;
+			return -1;
+		}
+	}
+
+	safe_offset = (off_t)*offset;
+	ret = sendfile(out_fd, in_fd, &safe_offset, count);
+	*offset = (uoff_t)safe_offset;
+
+	return ret;
+}
+
+#else
+ssize_t safe_sendfile(int out_fd __attr_unused__, int in_fd __attr_unused__,
+		      uoff_t *offset __attr_unused__,
+		      size_t count __attr_unused__)
+{
+	errno = EINVAL;
+	return -1;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/sendfile-util.h	Wed Aug 28 03:11:51 2002 +0300
@@ -0,0 +1,7 @@
+#ifndef __SENDFILE_UTIL_H
+#define __SENDFILE_UTIL_H
+
+/* simple wrapper for sendfile(), allowing usage of 64bit off_t with it */
+ssize_t safe_sendfile(int out_fd, int in_fd, uoff_t *offset, size_t count);
+
+#endif