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#define APR_WANT_MEMFUNC 19251876Speter#include "apr_want.h" 20251876Speter 21251876Speterstatic apr_status_t pool_bucket_cleanup(void *data) 22251876Speter{ 23251876Speter apr_bucket_pool *p = data; 24251876Speter 25251876Speter /* 26251876Speter * If the pool gets cleaned up, we have to copy the data out 27251876Speter * of the pool and onto the heap. But the apr_buckets out there 28251876Speter * that point to this pool bucket need to be notified such that 29251876Speter * they can morph themselves into a regular heap bucket the next 30251876Speter * time they try to read. To avoid having to manipulate 31251876Speter * reference counts and b->data pointers, the apr_bucket_pool 32251876Speter * actually _contains_ an apr_bucket_heap as its first element, 33251876Speter * so the two share their apr_bucket_refcount member, and you 34251876Speter * can typecast a pool bucket struct to make it look like a 35251876Speter * regular old heap bucket struct. 36251876Speter */ 37251876Speter p->heap.base = apr_bucket_alloc(p->heap.alloc_len, p->list); 38251876Speter memcpy(p->heap.base, p->base, p->heap.alloc_len); 39251876Speter p->base = NULL; 40251876Speter p->pool = NULL; 41251876Speter 42251876Speter return APR_SUCCESS; 43251876Speter} 44251876Speter 45251876Speterstatic apr_status_t pool_bucket_read(apr_bucket *b, const char **str, 46251876Speter apr_size_t *len, apr_read_type_e block) 47251876Speter{ 48251876Speter apr_bucket_pool *p = b->data; 49251876Speter const char *base = p->base; 50251876Speter 51251876Speter if (p->pool == NULL) { 52251876Speter /* 53251876Speter * pool has been cleaned up... masquerade as a heap bucket from now 54251876Speter * on. subsequent bucket operations will use the heap bucket code. 55251876Speter */ 56251876Speter b->type = &apr_bucket_type_heap; 57251876Speter base = p->heap.base; 58251876Speter } 59251876Speter *str = base + b->start; 60251876Speter *len = b->length; 61251876Speter return APR_SUCCESS; 62251876Speter} 63251876Speter 64251876Speterstatic void pool_bucket_destroy(void *data) 65251876Speter{ 66251876Speter apr_bucket_pool *p = data; 67251876Speter 68251876Speter /* If the pool is cleaned up before the last reference goes 69251876Speter * away, the data is really now on the heap; heap_destroy() takes 70251876Speter * over. free() in heap_destroy() thinks it's freeing 71251876Speter * an apr_bucket_heap, when in reality it's freeing the whole 72251876Speter * apr_bucket_pool for us. 73251876Speter */ 74251876Speter if (p->pool) { 75251876Speter /* the shared resource is still in the pool 76251876Speter * because the pool has not been cleaned up yet 77251876Speter */ 78251876Speter if (apr_bucket_shared_destroy(p)) { 79251876Speter apr_pool_cleanup_kill(p->pool, p, pool_bucket_cleanup); 80251876Speter apr_bucket_free(p); 81251876Speter } 82251876Speter } 83251876Speter else { 84251876Speter /* the shared resource is no longer in the pool, it's 85251876Speter * on the heap, but this reference still thinks it's a pool 86251876Speter * bucket. we should just go ahead and pass control to 87251876Speter * heap_destroy() for it since it doesn't know any better. 88251876Speter */ 89251876Speter apr_bucket_type_heap.destroy(p); 90251876Speter } 91251876Speter} 92251876Speter 93251876SpeterAPU_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b, 94251876Speter const char *buf, apr_size_t length, apr_pool_t *pool) 95251876Speter{ 96251876Speter apr_bucket_pool *p; 97251876Speter 98251876Speter p = apr_bucket_alloc(sizeof(*p), b->list); 99251876Speter 100251876Speter /* XXX: we lose the const qualifier here which indicates 101251876Speter * there's something screwy with the API... 102251876Speter */ 103251876Speter /* XXX: why is this? buf is const, p->base is const... what's 104251876Speter * the problem? --jcw */ 105251876Speter p->base = (char *) buf; 106251876Speter p->pool = pool; 107251876Speter p->list = b->list; 108251876Speter 109251876Speter b = apr_bucket_shared_make(b, p, 0, length); 110251876Speter b->type = &apr_bucket_type_pool; 111251876Speter 112251876Speter /* pre-initialize heap bucket member */ 113251876Speter p->heap.alloc_len = length; 114251876Speter p->heap.base = NULL; 115251876Speter p->heap.free_func = apr_bucket_free; 116251876Speter 117251876Speter apr_pool_cleanup_register(p->pool, p, pool_bucket_cleanup, 118251876Speter apr_pool_cleanup_null); 119251876Speter return b; 120251876Speter} 121251876Speter 122251876SpeterAPU_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf, 123251876Speter apr_size_t length, 124251876Speter apr_pool_t *pool, 125251876Speter apr_bucket_alloc_t *list) 126251876Speter{ 127251876Speter apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); 128251876Speter 129251876Speter APR_BUCKET_INIT(b); 130251876Speter b->free = apr_bucket_free; 131251876Speter b->list = list; 132251876Speter return apr_bucket_pool_make(b, buf, length, pool); 133251876Speter} 134251876Speter 135251876SpeterAPU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pool = { 136251876Speter "POOL", 5, APR_BUCKET_DATA, 137251876Speter pool_bucket_destroy, 138251876Speter pool_bucket_read, 139251876Speter apr_bucket_setaside_noop, /* don't need to setaside thanks to the cleanup*/ 140251876Speter apr_bucket_shared_split, 141251876Speter apr_bucket_shared_copy 142251876Speter}; 143