1251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251876Speter * contributor license agreements.  See the NOTICE file distributed with
3251876Speter * this work for additional information regarding copyright ownership.
4251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251876Speter * (the "License"); you may not use this file except in compliance with
6251876Speter * the License.  You may obtain a copy of the License at
7251876Speter *
8251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251876Speter *
10251876Speter * Unless required by applicable law or agreed to in writing, software
11251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251876Speter * See the License for the specific language governing permissions and
14251876Speter * limitations under the License.
15251876Speter */
16251876Speter
17251876Speter#include "apr_buckets.h"
18251876Speter
19251876Speter#if APR_HAS_MMAP
20251876Speter
21251876Speterstatic apr_status_t mmap_bucket_read(apr_bucket *b, const char **str,
22251876Speter                                     apr_size_t *length, apr_read_type_e block)
23251876Speter{
24251876Speter    apr_bucket_mmap *m = b->data;
25251876Speter    apr_status_t ok;
26251876Speter    void *addr;
27251876Speter
28251876Speter    if (!m->mmap) {
29251876Speter        /* the apr_mmap_t was already cleaned up out from under us */
30251876Speter        return APR_EINVAL;
31251876Speter    }
32251876Speter
33251876Speter    ok = apr_mmap_offset(&addr, m->mmap, b->start);
34251876Speter    if (ok != APR_SUCCESS) {
35251876Speter        return ok;
36251876Speter    }
37251876Speter    *str = addr;
38251876Speter    *length = b->length;
39251876Speter    return APR_SUCCESS;
40251876Speter}
41251876Speter
42251876Speterstatic apr_status_t mmap_bucket_cleanup(void *data)
43251876Speter{
44251876Speter    /* the apr_mmap_t is about to disappear out from under us, so we
45251876Speter     * have no choice but to pretend it doesn't exist anymore.  the
46251876Speter     * refcount is now useless because there's nothing to refer to
47251876Speter     * anymore.  so the only valid action on any remaining referrer
48251876Speter     * is to delete it.  no more reads, no more anything. */
49251876Speter    apr_bucket_mmap *m = data;
50251876Speter
51251876Speter    m->mmap = NULL;
52251876Speter    return APR_SUCCESS;
53251876Speter}
54251876Speter
55251876Speterstatic void mmap_bucket_destroy(void *data)
56251876Speter{
57251876Speter    apr_bucket_mmap *m = data;
58251876Speter
59251876Speter    if (apr_bucket_shared_destroy(m)) {
60251876Speter        if (m->mmap) {
61251876Speter            apr_pool_cleanup_kill(m->mmap->cntxt, m, mmap_bucket_cleanup);
62251876Speter            apr_mmap_delete(m->mmap);
63251876Speter        }
64251876Speter        apr_bucket_free(m);
65251876Speter    }
66251876Speter}
67251876Speter
68251876Speter/*
69251876Speter * XXX: are the start and length arguments useful?
70251876Speter */
71251876SpeterAPU_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm,
72251876Speter                                               apr_off_t start,
73251876Speter                                               apr_size_t length)
74251876Speter{
75251876Speter    apr_bucket_mmap *m;
76251876Speter
77251876Speter    m = apr_bucket_alloc(sizeof(*m), b->list);
78251876Speter    m->mmap = mm;
79251876Speter
80251876Speter    apr_pool_cleanup_register(mm->cntxt, m, mmap_bucket_cleanup,
81251876Speter                              apr_pool_cleanup_null);
82251876Speter
83251876Speter    b = apr_bucket_shared_make(b, m, start, length);
84251876Speter    b->type = &apr_bucket_type_mmap;
85251876Speter
86251876Speter    return b;
87251876Speter}
88251876Speter
89251876Speter
90251876SpeterAPU_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm,
91251876Speter                                                 apr_off_t start,
92251876Speter                                                 apr_size_t length,
93251876Speter                                                 apr_bucket_alloc_t *list)
94251876Speter{
95251876Speter    apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
96251876Speter
97251876Speter    APR_BUCKET_INIT(b);
98251876Speter    b->free = apr_bucket_free;
99251876Speter    b->list = list;
100251876Speter    return apr_bucket_mmap_make(b, mm, start, length);
101251876Speter}
102251876Speter
103251876Speterstatic apr_status_t mmap_bucket_setaside(apr_bucket *b, apr_pool_t *p)
104251876Speter{
105251876Speter    apr_bucket_mmap *m = b->data;
106251876Speter    apr_mmap_t *mm = m->mmap;
107251876Speter    apr_mmap_t *new_mm;
108251876Speter    apr_status_t ok;
109251876Speter
110251876Speter    if (!mm) {
111251876Speter        /* the apr_mmap_t was already cleaned up out from under us */
112251876Speter        return APR_EINVAL;
113251876Speter    }
114251876Speter
115251876Speter    /* shortcut if possible */
116251876Speter    if (apr_pool_is_ancestor(mm->cntxt, p)) {
117251876Speter        return APR_SUCCESS;
118251876Speter    }
119251876Speter
120251876Speter    /* duplicate apr_mmap_t into new pool */
121251876Speter    ok = apr_mmap_dup(&new_mm, mm, p);
122251876Speter    if (ok != APR_SUCCESS) {
123251876Speter        return ok;
124251876Speter    }
125251876Speter
126251876Speter    /* decrement refcount on old apr_bucket_mmap */
127251876Speter    mmap_bucket_destroy(m);
128251876Speter
129251876Speter    /* create new apr_bucket_mmap pointing to new apr_mmap_t */
130251876Speter    apr_bucket_mmap_make(b, new_mm, b->start, b->length);
131251876Speter
132251876Speter    return APR_SUCCESS;
133251876Speter}
134251876Speter
135251876SpeterAPU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_mmap = {
136251876Speter    "MMAP", 5, APR_BUCKET_DATA,
137251876Speter    mmap_bucket_destroy,
138251876Speter    mmap_bucket_read,
139251876Speter    mmap_bucket_setaside,
140251876Speter    apr_bucket_shared_split,
141251876Speter    apr_bucket_shared_copy
142251876Speter};
143251876Speter
144251876Speter#endif
145