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