libmicrohttpd

HTTP/1.x server C library (MHD 1.x, stable)
Log | Files | Refs | Submodules | README | LICENSE

commit 09088de0dbfb52843d4a960041b1f560b4c0e1b1
parent b218fd29ff2dbbad26eaecce1abe65ba3e791bdf
Author: Evgeny Grin (Karlson2k) <k2k@narod.ru>
Date:   Tue,  9 Jun 2015 19:33:57 +0000

Add MHD_create_response_from_fd64() and MHD_create_response_from_fd_at_offset64() functions,
check lseek() results when reading file, check whether desired file offset fits off_t

Diffstat:
Msrc/include/microhttpd.h | 51++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/microhttpd/internal.h | 2+-
Msrc/microhttpd/response.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 107 insertions(+), 10 deletions(-)

diff --git a/src/include/microhttpd.h b/src/include/microhttpd.h @@ -2076,11 +2076,27 @@ MHD_create_response_from_buffer (size_t size, * @return NULL on error (i.e. invalid arguments, out of memory) * @ingroup response */ -/* NOTE: this should be 'uint64_t' instead of 'size_t', but changing - this would break API compatibility. */ _MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd (size_t size, - int fd); + int fd); + + +/** + * Create a response object. The response object can be extended with + * header information and then be used any number of times. + * + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd64 (uint64_t size, + int fd); /** @@ -2099,12 +2115,33 @@ MHD_create_response_from_fd (size_t size, * @return NULL on error (i.e. invalid arguments, out of memory) * @ingroup response */ -/* NOTE: this should be 'uint64_t' instead of 'size_t', but changing - this would break API compatibility. */ +_MHD_DEPR_FUNC("Function MHD_create_response_from_fd_at_offset() is deprecated, use MHD_create_response_from_fd_at_offset64()") \ _MHD_EXTERN struct MHD_Response * MHD_create_response_from_fd_at_offset (size_t size, - int fd, - off_t offset); + int fd, + off_t offset); + + +/** + * Create a response object. The response object can be extended with + * header information and then be used any number of times. + * + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @param offset offset to start reading from in the file; + * reading file beyond 2 GiB may be not supported by OS or + * MHD build + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd_at_offset64 (uint64_t size, + int fd, + uint64_t offset); #if 0 diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h @@ -295,7 +295,7 @@ struct MHD_Response /** * Offset to start reading from when using @e fd. */ - off_t fd_off; + uint64_t fd_off; /** * Number of bytes ready in @e data (buffer may be larger diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c @@ -28,6 +28,7 @@ #include "internal.h" #include "response.h" +#include <limits.h> #if defined(_WIN32) && defined(MHD_W32_MUTEX_) #ifndef WIN32_LEAN_AND_MEAN @@ -304,6 +305,10 @@ MHD_set_response_options (struct MHD_Response *response, } +#ifndef INT32_MAX +#define INT32_MAX ((int32_t)0x7FFFFFFF) +#endif /* !INT32_MAX */ + /** * Given a file descriptor, read data from the file * to generate the response. @@ -319,8 +324,17 @@ file_reader (void *cls, uint64_t pos, char *buf, size_t max) { struct MHD_Response *response = cls; ssize_t n; + const int64_t offset64 = (int64_t)(pos + response->fd_off); + + if (offset64 < 0) + return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */ + + if (sizeof(off_t) < sizeof(uint64_t) && offset64 > (uint64_t)INT32_MAX) + return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */ + + if (lseek (response->fd, (off_t)offset64, SEEK_SET) != (off_t)offset64) + return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */ - (void) lseek (response->fd, pos + response->fd_off, SEEK_SET); n = read (response->fd, buf, max); if (0 == n) return MHD_CONTENT_READER_END_OF_STREAM; @@ -367,6 +381,31 @@ MHD_create_response_from_fd_at_offset (size_t size, int fd, off_t offset) { + return MHD_create_response_from_fd_at_offset64 (size, fd, offset); +} + + +/** + * Create a response object. The response object can be extended with + * header information and then be used any number of times. + * + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @param offset offset to start reading from in the file; + * reading file beyond 2 GiB may be not supported by OS or + * MHD build + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd_at_offset64 (uint64_t size, + int fd, + uint64_t offset) +{ struct MHD_Response *response; response = MHD_create_response_from_callback (size, @@ -396,7 +435,28 @@ struct MHD_Response * MHD_create_response_from_fd (size_t size, int fd) { - return MHD_create_response_from_fd_at_offset (size, fd, 0); + return MHD_create_response_from_fd_at_offset64 (size, fd, 0); +} + + +/** + * Create a response object. The response object can be extended with + * header information and then be used any number of times. + * + * @param size size of the data portion of the response; + * sizes larger than 2 GiB may be not supported by OS or + * MHD build + * @param fd file descriptor referring to a file on disk with the + * data; will be closed when response is destroyed; + * fd should be in 'blocking' mode + * @return NULL on error (i.e. invalid arguments, out of memory) + * @ingroup response + */ +_MHD_EXTERN struct MHD_Response * +MHD_create_response_from_fd64(uint64_t size, + int fd) +{ + return MHD_create_response_from_fd_at_offset64 (size, fd, 0); }