# HG changeset patch # User Timo Sirainen # Date 1030493511 -10800 # Node ID 8aaa39e7aec89e1d9481e65cb67d40f8bb8ea040 # Parent 2d2e2594e60faffcc1cbafa22d6433e22bfce922 sendfile() works now properly with 64bit off_t diff -r 2d2e2594e60f -r 8aaa39e7aec8 src/lib/Makefile.am --- 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 \ diff -r 2d2e2594e60f -r 8aaa39e7aec8 src/lib/iobuffer.c --- 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 -#ifdef HAVE_SYS_SENDFILE_H -# include -#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) diff -r 2d2e2594e60f -r 8aaa39e7aec8 src/lib/sendfile-util.c --- /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 + +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 diff -r 2d2e2594e60f -r 8aaa39e7aec8 src/lib/sendfile-util.h --- /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