GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
response_from_fd.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007-2019 Daniel Pittman, Christian Grothoff and
4 Karlson2k (Evgeny Grin)
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
28#include "internal.h"
29
30
35#ifndef MHD_FILE_READ_BLOCK_SIZE
36#ifdef _WIN32
37#define MHD_FILE_READ_BLOCK_SIZE 16384 /* 16k */
38#else /* _WIN32 */
39#define MHD_FILE_READ_BLOCK_SIZE 4096 /* 4k */
40#endif /* _WIN32 */
41#endif /* !MHD_FD_BLOCK_SIZE */
42
53static ssize_t
54file_reader (void *cls,
55 uint64_t pos,
56 char *buf,
57 size_t max)
58{
59 struct MHD_Response *response = cls;
60#if ! defined(_WIN32) || defined(__CYGWIN__)
61 ssize_t n;
62#else /* _WIN32 && !__CYGWIN__ */
63 const HANDLE fh = (HANDLE) _get_osfhandle (response->fd);
64#endif /* _WIN32 && !__CYGWIN__ */
65 const int64_t offset64 = (int64_t) (pos + response->fd_off);
66
67 if (offset64 < 0)
68 return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
69
70#if ! defined(_WIN32) || defined(__CYGWIN__)
71 if (max > SSIZE_MAX)
72 max = SSIZE_MAX; /* Clamp to maximum return value. */
73
74#if defined(HAVE_PREAD64)
75 n = pread64 (response->fd,
76 buf,
77 max,
78 offset64);
79#elif defined(HAVE_PREAD)
80 if ( (sizeof(off_t) < sizeof (uint64_t)) &&
81 (offset64 > (uint64_t) INT32_MAX) )
82 return MHD_CONTENT_READER_END_WITH_ERROR; /* Read at required position is not possible. */
83
84 n = pread (response->fd,
85 buf,
86 max,
87 (off_t) offset64);
88#else /* ! HAVE_PREAD */
89#if defined(HAVE_LSEEK64)
90 if (lseek64 (response->fd,
91 offset64,
92 SEEK_SET) != offset64)
93 return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
94#else /* ! HAVE_LSEEK64 */
95 if ( (sizeof(off_t) < sizeof (uint64_t)) &&
96 (offset64 > (uint64_t) INT32_MAX) )
97 return MHD_CONTENT_READER_END_WITH_ERROR; /* seek to required position is not possible */
98
99 if (lseek (response->fd,
100 (off_t) offset64,
101 SEEK_SET) != (off_t) offset64)
102 return MHD_CONTENT_READER_END_WITH_ERROR; /* can't seek to required position */
103#endif /* ! HAVE_LSEEK64 */
104 n = read (response->fd,
105 buf,
106 max);
107
108#endif /* ! HAVE_PREAD */
109 if (0 == n)
111 if (n < 0)
113 return n;
114#else /* _WIN32 && !__CYGWIN__ */
115 if (INVALID_HANDLE_VALUE == fh)
116 return MHD_CONTENT_READER_END_WITH_ERROR; /* Value of 'response->fd' is not valid. */
117 else
118 {
119 OVERLAPPED f_ol = {0, 0, {{0, 0}}, 0}; /* Initialize to zero. */
120 ULARGE_INTEGER pos_uli;
121 DWORD toRead = (max > INT32_MAX) ? INT32_MAX : (DWORD) max;
122 DWORD resRead;
123
124 pos_uli.QuadPart = (uint64_t) offset64; /* Simple transformation 64bit -> 2x32bit. */
125 f_ol.Offset = pos_uli.LowPart;
126 f_ol.OffsetHigh = pos_uli.HighPart;
127 if (! ReadFile (fh,
128 (void *) buf,
129 toRead,
130 &resRead,
131 &f_ol))
132 return MHD_CONTENT_READER_END_WITH_ERROR; /* Read error. */
133 if (0 == resRead)
135 return (ssize_t) resRead;
136 }
137#endif /* _WIN32 && !__CYGWIN__ */
138}
139
140
147static void
148free_callback (void *cls)
149{
150 struct MHD_Response *response = cls;
151
152 (void) close (response->fd);
153 response->fd = -1;
154}
155
156
175struct MHD_Response *
176MHD_response_from_fd (enum MHD_HTTP_StatusCode sc,
177 int fd,
178 uint64_t offset,
179 uint64_t size)
180{
181 struct MHD_Response *response;
182
183 mhd_assert (-1 != fd);
184#if ! defined(HAVE___LSEEKI64) && ! defined(HAVE_LSEEK64)
185 if ( (sizeof (uint64_t) > sizeof (off_t)) &&
186 ( (size > (uint64_t) INT32_MAX) ||
187 (offset > (uint64_t) INT32_MAX) ||
188 ((size + offset) >= (uint64_t) INT32_MAX) ) )
189 return NULL;
190#endif
191 if ( ((int64_t) size < 0) ||
192 ((int64_t) offset < 0) ||
193 ((int64_t) (size + offset) < 0) )
194 return NULL;
195
196 response = MHD_response_from_callback (sc,
197 size,
200 NULL,
202 if (NULL == response)
203 return NULL;
204 response->fd = fd;
205 response->fd_off = offset;
206 response->crc_cls = response;
207 return response;
208}
209
210
211/* end of response_from_fd.c */
struct MHD_Response * MHD_response_from_callback(enum MHD_HTTP_StatusCode sc, uint64_t size, size_t block_size, MHD_ContentReaderCallback crc, void *crc_cls, MHD_ContentReaderFreeCallback crfc)
struct MHD_Response * MHD_response_from_fd(enum MHD_HTTP_StatusCode sc, int fd, uint64_t offset, uint64_t size)
#define mhd_assert(CHK)
Definition mhd_assert.h:39
#define INT32_MAX
Definition mhd_limits.h:65
#define NULL
MHD internal shared structures.
#define SSIZE_MAX
Definition mhd_limits.h:113
int off_t offset
#define MHD_CONTENT_READER_END_OF_STREAM
Definition microhttpd.h:187
int fd
#define MHD_CONTENT_READER_END_WITH_ERROR
Definition microhttpd.h:188
static void free_callback(void *cls)
#define MHD_FILE_READ_BLOCK_SIZE
static ssize_t file_reader(void *cls, uint64_t pos, char *buf, size_t max)
void * crc_cls
Definition internal.h:1594
uint64_t fd_off
Definition internal.h:1653