1169691Skan/* Licensed to the Apache Software Foundation (ASF) under one or more 2169691Skan * contributor license agreements. See the NOTICE file distributed with 3169691Skan * this work for additional information regarding copyright ownership. 4169691Skan * The ASF licenses this file to You under the Apache License, Version 2.0 5169691Skan * (the "License"); you may not use this file except in compliance with 6169691Skan * the License. You may obtain a copy of the License at 7169691Skan * 8169691Skan * http://www.apache.org/licenses/LICENSE-2.0 9169691Skan * 10169691Skan * Unless required by applicable law or agreed to in writing, software 11169691Skan * distributed under the License is distributed on an "AS IS" BASIS, 12169691Skan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13169691Skan * See the License for the specific language governing permissions and 14169691Skan * limitations under the License. 15169691Skan */ 16169691Skan 17169691Skan#include "apr_buckets.h" 18169691Skan#define APR_WANT_MEMFUNC 19169691Skan#include "apr_want.h" 20169691Skan 21169691Skanstatic apr_status_t pool_bucket_cleanup(void *data) 22169691Skan{ 23169691Skan apr_bucket_pool *p = data; 24169691Skan 25169691Skan /* 26169691Skan * If the pool gets cleaned up, we have to copy the data out 27169691Skan * of the pool and onto the heap. But the apr_buckets out there 28169691Skan * that point to this pool bucket need to be notified such that 29169691Skan * they can morph themselves into a regular heap bucket the next 30169691Skan * time they try to read. To avoid having to manipulate 31169691Skan * reference counts and b->data pointers, the apr_bucket_pool 32169691Skan * actually _contains_ an apr_bucket_heap as its first element, 33169691Skan * so the two share their apr_bucket_refcount member, and you 34169691Skan * can typecast a pool bucket struct to make it look like a 35169691Skan * regular old heap bucket struct. 36169691Skan */ 37169691Skan p->heap.base = apr_bucket_alloc(p->heap.alloc_len, p->list); 38169691Skan memcpy(p->heap.base, p->base, p->heap.alloc_len); 39169691Skan p->base = NULL; 40169691Skan p->pool = NULL; 41169691Skan 42169691Skan return APR_SUCCESS; 43169691Skan} 44169691Skan 45169691Skanstatic apr_status_t pool_bucket_read(apr_bucket *b, const char **str, 46169691Skan apr_size_t *len, apr_read_type_e block) 47169691Skan{ 48169691Skan apr_bucket_pool *p = b->data; 49169691Skan const char *base = p->base; 50169691Skan 51169691Skan if (p->pool == NULL) { 52169691Skan /* 53169691Skan * pool has been cleaned up... masquerade as a heap bucket from now 54169691Skan * on. subsequent bucket operations will use the heap bucket code. 55169691Skan */ 56169691Skan b->type = &apr_bucket_type_heap; 57169691Skan base = p->heap.base; 58169691Skan } 59169691Skan *str = base + b->start; 60169691Skan *len = b->length; 61169691Skan return APR_SUCCESS; 62169691Skan} 63169691Skan 64169691Skanstatic void pool_bucket_destroy(void *data) 65169691Skan{ 66169691Skan apr_bucket_pool *p = data; 67169691Skan 68169691Skan /* If the pool is cleaned up before the last reference goes 69169691Skan * away, the data is really now on the heap; heap_destroy() takes 70169691Skan * over. free() in heap_destroy() thinks it's freeing 71169691Skan * an apr_bucket_heap, when in reality it's freeing the whole 72169691Skan * apr_bucket_pool for us. 73169691Skan */ 74169691Skan if (p->pool) { 75169691Skan /* the shared resource is still in the pool 76169691Skan * because the pool has not been cleaned up yet 77169691Skan */ 78169691Skan if (apr_bucket_shared_destroy(p)) { 79169691Skan apr_pool_cleanup_kill(p->pool, p, pool_bucket_cleanup); 80169691Skan apr_bucket_free(p); 81169691Skan } 82169691Skan } 83169691Skan else { 84169691Skan /* the shared resource is no longer in the pool, it's 85169691Skan * on the heap, but this reference still thinks it's a pool 86169691Skan * bucket. we should just go ahead and pass control to 87169691Skan * heap_destroy() for it since it doesn't know any better. 88169691Skan */ 89169691Skan apr_bucket_type_heap.destroy(p); 90169691Skan } 91169691Skan} 92169691Skan 93169691SkanAPU_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b, 94169691Skan const char *buf, apr_size_t length, apr_pool_t *pool) 95169691Skan{ 96169691Skan apr_bucket_pool *p; 97169691Skan 98169691Skan p = apr_bucket_alloc(sizeof(*p), b->list); 99169691Skan 100169691Skan /* XXX: we lose the const qualifier here which indicates 101169691Skan * there's something screwy with the API... 102169691Skan */ 103169691Skan /* XXX: why is this? buf is const, p->base is const... what's 104169691Skan * the problem? --jcw */ 105169691Skan p->base = (char *) buf; 106169691Skan p->pool = pool; 107169691Skan p->list = b->list; 108 109 b = apr_bucket_shared_make(b, p, 0, length); 110 b->type = &apr_bucket_type_pool; 111 112 /* pre-initialize heap bucket member */ 113 p->heap.alloc_len = length; 114 p->heap.base = NULL; 115 p->heap.free_func = apr_bucket_free; 116 117 apr_pool_cleanup_register(p->pool, p, pool_bucket_cleanup, 118 apr_pool_cleanup_null); 119 return b; 120} 121 122APU_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf, 123 apr_size_t length, 124 apr_pool_t *pool, 125 apr_bucket_alloc_t *list) 126{ 127 apr_bucket *b = apr_bucket_alloc(sizeof(*b), list); 128 129 APR_BUCKET_INIT(b); 130 b->free = apr_bucket_free; 131 b->list = list; 132 return apr_bucket_pool_make(b, buf, length, pool); 133} 134 135APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pool = { 136 "POOL", 5, APR_BUCKET_DATA, 137 pool_bucket_destroy, 138 pool_bucket_read, 139 apr_bucket_setaside_noop, /* don't need to setaside thanks to the cleanup*/ 140 apr_bucket_shared_split, 141 apr_bucket_shared_copy 142}; 143