/src/httpd/srclib/apr/buckets/apr_buckets_mmap.c
Line | Count | Source (jump to first uncovered line) |
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_buckets.h" |
18 | | |
19 | | #if APR_HAS_MMAP |
20 | | |
21 | | static apr_status_t mmap_bucket_read(apr_bucket *b, const char **str, |
22 | | apr_size_t *length, apr_read_type_e block) |
23 | 0 | { |
24 | 0 | apr_bucket_mmap *m = b->data; |
25 | 0 | apr_status_t ok; |
26 | 0 | void *addr; |
27 | |
|
28 | 0 | if (!m->mmap) { |
29 | | /* the apr_mmap_t was already cleaned up out from under us */ |
30 | 0 | return APR_EINVAL; |
31 | 0 | } |
32 | | |
33 | 0 | ok = apr_mmap_offset(&addr, m->mmap, b->start); |
34 | 0 | if (ok != APR_SUCCESS) { |
35 | 0 | return ok; |
36 | 0 | } |
37 | 0 | *str = addr; |
38 | 0 | *length = b->length; |
39 | 0 | return APR_SUCCESS; |
40 | 0 | } |
41 | | |
42 | | static apr_status_t mmap_bucket_cleanup(void *data) |
43 | 0 | { |
44 | | /* the apr_mmap_t is about to disappear out from under us, so we |
45 | | * have no choice but to pretend it doesn't exist anymore. the |
46 | | * refcount is now useless because there's nothing to refer to |
47 | | * anymore. so the only valid action on any remaining referrer |
48 | | * is to delete it. no more reads, no more anything. */ |
49 | 0 | apr_bucket_mmap *m = data; |
50 | |
|
51 | 0 | m->mmap = NULL; |
52 | 0 | return APR_SUCCESS; |
53 | 0 | } |
54 | | |
55 | | static void mmap_bucket_destroy(void *data) |
56 | 0 | { |
57 | 0 | apr_bucket_mmap *m = data; |
58 | |
|
59 | 0 | if (apr_bucket_shared_destroy(m)) { |
60 | 0 | if (m->mmap) { |
61 | 0 | apr_pool_cleanup_kill(m->mmap->cntxt, m, mmap_bucket_cleanup); |
62 | 0 | apr_mmap_delete(m->mmap); |
63 | 0 | } |
64 | 0 | apr_bucket_free(m); |
65 | 0 | } |
66 | 0 | } |
67 | | |
68 | | /* |
69 | | * XXX: are the start and length arguments useful? |
70 | | */ |
71 | | APR_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm, |
72 | | apr_off_t start, |
73 | | apr_size_t length) |
74 | 0 | { |
75 | 0 | apr_bucket_mmap *m; |
76 | |
|
77 | 0 | m = apr_bucket_alloc(sizeof(*m), b->list); |
78 | 0 | m->mmap = mm; |
79 | |
|
80 | 0 | apr_pool_cleanup_register(mm->cntxt, m, mmap_bucket_cleanup, |
81 | 0 | apr_pool_cleanup_null); |
82 | |
|
83 | 0 | b = apr_bucket_shared_make(b, m, start, length); |
84 | 0 | b->type = &apr_bucket_type_mmap; |
85 | |
|
86 | 0 | return b; |
87 | 0 | } |
88 | | |
89 | | |
90 | | APR_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm, |
91 | | apr_off_t start, |
92 | | apr_size_t length, |
93 | | apr_bucket_alloc_t *list) |
94 | 0 | { |
95 | 0 | apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); |
96 | |
|
97 | 0 | APR_BUCKET_INIT(b); |
98 | 0 | b->free = apr_bucket_free; |
99 | 0 | b->list = list; |
100 | 0 | return apr_bucket_mmap_make(b, mm, start, length); |
101 | 0 | } |
102 | | |
103 | | static apr_status_t mmap_bucket_setaside(apr_bucket *b, apr_pool_t *p) |
104 | 0 | { |
105 | 0 | apr_bucket_mmap *m = b->data; |
106 | 0 | apr_mmap_t *mm = m->mmap; |
107 | 0 | apr_mmap_t *new_mm; |
108 | 0 | apr_status_t ok; |
109 | |
|
110 | 0 | if (!mm) { |
111 | | /* the apr_mmap_t was already cleaned up out from under us */ |
112 | 0 | return APR_EINVAL; |
113 | 0 | } |
114 | | |
115 | | /* shortcut if possible */ |
116 | 0 | if (apr_pool_is_ancestor(mm->cntxt, p)) { |
117 | 0 | return APR_SUCCESS; |
118 | 0 | } |
119 | | |
120 | | /* duplicate apr_mmap_t into new pool */ |
121 | 0 | ok = apr_mmap_dup(&new_mm, mm, p); |
122 | 0 | if (ok != APR_SUCCESS) { |
123 | 0 | return ok; |
124 | 0 | } |
125 | | |
126 | | /* decrement refcount on old apr_bucket_mmap */ |
127 | 0 | mmap_bucket_destroy(m); |
128 | | |
129 | | /* create new apr_bucket_mmap pointing to new apr_mmap_t */ |
130 | 0 | apr_bucket_mmap_make(b, new_mm, b->start, b->length); |
131 | |
|
132 | 0 | return APR_SUCCESS; |
133 | 0 | } |
134 | | |
135 | | APR_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_mmap = { |
136 | | "MMAP", 5, APR_BUCKET_DATA, |
137 | | mmap_bucket_destroy, |
138 | | mmap_bucket_read, |
139 | | mmap_bucket_setaside, |
140 | | apr_bucket_shared_split, |
141 | | apr_bucket_shared_copy |
142 | | }; |
143 | | |
144 | | #endif |