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:
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);
}