Apache HTTPD
apr_buckets_file.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr.h"
18#include "apr_general.h"
19#include "apr_file_io.h"
20#include "apr_buckets.h"
21
22#if APR_HAS_MMAP
23#include "apr_mmap.h"
24
25/* mmap support for static files based on ideas from John Heidemann's
26 * patch against 1.0.5. See
27 * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
28 */
29
30#endif /* APR_HAS_MMAP */
31
32static void file_bucket_destroy(void *data)
33{
35
37 /* no need to close the file here; it will get
38 * done automatically when the pool gets cleaned up */
40 }
41}
42
43#if APR_HAS_MMAP
46{
48 apr_mmap_t *mm;
49
50 if (!a->can_mmap) {
51 return 0;
52 }
53
57 {
58 return 0;
59 }
62 }
63 else if ((filelength < APR_MMAP_THRESHOLD) ||
66 {
67 return 0;
68 }
71 return 1;
72}
73#endif
74
77{
79 apr_file_t *f = a->fd;
80 apr_bucket *b = NULL;
81 char *buf;
82 apr_status_t rv;
83 apr_size_t filelength = e->length; /* bytes remaining in file past offset */
85#if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES
87#endif
88
89#if APR_HAS_MMAP
90 if (file_make_mmap(e, filelength, fileoffset, a->readpool)) {
91 return apr_bucket_read(e, str, len, block);
92 }
93#endif
94
95#if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES
97 /* this file descriptor is shared across multiple threads and
98 * this OS doesn't support that natively, so as a workaround
99 * we must reopen the file into a->readpool */
100 const char *fname;
102
103 rv = apr_file_open(&f, fname, (flags & ~APR_FOPEN_XTHREAD), 0, a->readpool);
104 if (rv != APR_SUCCESS)
105 return rv;
106
107 a->fd = f;
108 }
109#endif
110
111 *str = NULL; /* in case we die prematurely */
112 *len = (filelength > a->read_size) ? a->read_size : filelength;
114
115 /* Handle offset ... */
117 if (rv != APR_SUCCESS) {
119 return rv;
120 }
121 rv = apr_file_read(f, buf, len);
122 if (rv != APR_SUCCESS && rv != APR_EOF) {
124 return rv;
125 }
126 filelength -= *len;
127 /*
128 * Change the current bucket to refer to what we read,
129 * even if we read nothing because we hit EOF.
130 */
132
133 /* If we have more to read from the file, then create another bucket */
134 if (filelength > 0 && rv != APR_EOF) {
135 /* for efficiency, we can just build a new apr_bucket struct
136 * to wrap around the existing file bucket */
137 b = apr_bucket_alloc(sizeof(*b), e->list);
138 b->start = fileoffset + (*len);
139 b->length = filelength;
140 b->data = a;
141 b->type = &apr_bucket_type_file;
142 b->free = apr_bucket_free;
143 b->list = e->list;
145 }
146 else {
148 }
149
150 *str = buf;
151 return rv;
152}
153
157{
159
160 f = apr_bucket_alloc(sizeof(*f), b->list);
161 f->fd = fd;
162 f->readpool = p;
163#if APR_HAS_MMAP
164 f->can_mmap = 1;
165#endif
166 f->read_size = APR_BUCKET_BUFF_SIZE;
167
169 b->type = &apr_bucket_type_file;
170
171 return b;
172}
173
178{
179 apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
180
182 b->free = apr_bucket_free;
183 b->list = list;
184 return apr_bucket_file_make(b, fd, offset, len, p);
185}
186
188 int enabled)
189{
190#if APR_HAS_MMAP
192 a->can_mmap = enabled;
193 return APR_SUCCESS;
194#else
195 return APR_ENOTIMPL;
196#endif /* APR_HAS_MMAP */
197}
198
201{
203
204 if (size <= APR_BUCKET_BUFF_SIZE) {
205 a->read_size = APR_BUCKET_BUFF_SIZE;
206 }
207 else {
209 a->read_size = (size < floor) ? size : floor;
210 }
211
212 return APR_SUCCESS;
213}
214
216{
217 apr_bucket_file *a = b->data;
218 apr_file_t *fd = NULL;
219 apr_file_t *f = a->fd;
221
223 return APR_SUCCESS;
224 }
225
226 /* If the file is shared/split accross multiple buckets, this bucket can't
227 * take exclusive ownership with apr_file_setaside() (thus invalidating the
228 * f->filedes), let's apr_file_dup() in this case instead.
229 */
230 if (a->refcount.refcount > 1) {
231 apr_bucket_file *new;
232 apr_status_t rv;
233
234 rv = apr_file_dup(&fd, f, reqpool);
235 if (rv != APR_SUCCESS) {
236 return rv;
237 }
238
239 new = apr_bucket_alloc(sizeof(*new), b->list);
240 memcpy(new, a, sizeof(*new));
241 new->refcount.refcount = 1;
242 new->readpool = reqpool;
243
244 a->refcount.refcount--;
245 a = b->data = new;
246 }
247 else {
249 if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
250 a->readpool = reqpool;
251 }
252 }
253 a->fd = fd;
254 return APR_SUCCESS;
255}
256
const char apr_size_t len
Definition ap_regex.h:187
APR-UTIL Buckets/Bucket Brigades.
static void file_bucket_destroy(void *data)
static apr_status_t file_bucket_read(apr_bucket *e, const char **str, apr_size_t *len, apr_read_type_e block)
static apr_status_t file_bucket_setaside(apr_bucket *b, apr_pool_t *reqpool)
APR File I/O Handling.
APR Miscellaneous library routines.
APR MMAP routines.
APU_DECLARE(void)
Computes SipHash-2-4, producing a 64bit (APR_SIPHASH_DSIZE) hash from a message and a 128bit (APR_SIP...
Definition apr_sha1.c:206
const unsigned char * buf
Definition util_md5.h:50
#define APR_EOF
Definition apr_errno.h:461
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_BUCKET_INIT(e)
int enabled
apr_file_t * f
#define APR_BUCKET_INSERT_AFTER(a, b)
#define apr_bucket_split(e, point)
apr_read_type_e
Definition apr_buckets.h:57
apr_bucket * e
#define APR_BUCKET_BUFF_SIZE
Definition apr_buckets.h:54
APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_file
apr_bucket apr_bucket_brigade * a
apr_file_t * fd
#define apr_bucket_read(e, str, len, block)
const char apr_ssize_t int flags
Definition apr_encode.h:168
apr_size_t size
const apr_array_header_t * list
Definition apr_cstr.h:105
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
apr_seek_where_t apr_off_t * offset
void * data
#define APR_FOPEN_XTHREAD
Definition apr_file_io.h:67
#define APR_SET
const char * fname
#define APR_MMAP_READ
Definition apr_mmap.h:46
apr_pool_t * b
Definition apr_pools.h:529
apr_pool_t * p
Definition md_event.c:32
return NULL
Definition mod_so.c:359
apr_size_t length
apr_off_t start
apr_bucket_alloc_t * list
void * data
#define str