155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2002 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "krb5_locl.h" 35102644Snectar#include "store-int.h" 3655682Smarkm 3755682Smarkmtypedef struct emem_storage{ 3855682Smarkm unsigned char *base; 3955682Smarkm size_t size; 4055682Smarkm size_t len; 4155682Smarkm unsigned char *ptr; 4255682Smarkm}emem_storage; 4355682Smarkm 4455682Smarkmstatic ssize_t 4555682Smarkmemem_fetch(krb5_storage *sp, void *data, size_t size) 4655682Smarkm{ 4755682Smarkm emem_storage *s = (emem_storage*)sp->data; 48233294Sstas if((size_t)(s->base + s->len - s->ptr) < size) 4955682Smarkm size = s->base + s->len - s->ptr; 5055682Smarkm memmove(data, s->ptr, size); 5155682Smarkm sp->seek(sp, size, SEEK_CUR); 5255682Smarkm return size; 5355682Smarkm} 5455682Smarkm 5555682Smarkmstatic ssize_t 5672445Sassaremem_store(krb5_storage *sp, const void *data, size_t size) 5755682Smarkm{ 5855682Smarkm emem_storage *s = (emem_storage*)sp->data; 59233294Sstas if(size > (size_t)(s->base + s->size - s->ptr)){ 6055682Smarkm void *base; 6155682Smarkm size_t sz, off; 6255682Smarkm off = s->ptr - s->base; 63107207Snectar sz = off + size; 64107207Snectar if (sz < 4096) 65107207Snectar sz *= 2; 6655682Smarkm base = realloc(s->base, sz); 6755682Smarkm if(base == NULL) 68233294Sstas return -1; 6955682Smarkm s->size = sz; 7055682Smarkm s->base = base; 7155682Smarkm s->ptr = (unsigned char*)base + off; 7255682Smarkm } 7355682Smarkm memmove(s->ptr, data, size); 7455682Smarkm sp->seek(sp, size, SEEK_CUR); 7555682Smarkm return size; 7655682Smarkm} 7755682Smarkm 7855682Smarkmstatic off_t 7955682Smarkmemem_seek(krb5_storage *sp, off_t offset, int whence) 8055682Smarkm{ 8155682Smarkm emem_storage *s = (emem_storage*)sp->data; 8255682Smarkm switch(whence){ 8355682Smarkm case SEEK_SET: 84233294Sstas if((size_t)offset > s->size) 8555682Smarkm offset = s->size; 8655682Smarkm if(offset < 0) 8755682Smarkm offset = 0; 8855682Smarkm s->ptr = s->base + offset; 89233294Sstas if((size_t)offset > s->len) 9055682Smarkm s->len = offset; 9155682Smarkm break; 9255682Smarkm case SEEK_CUR: 9355682Smarkm sp->seek(sp,s->ptr - s->base + offset, SEEK_SET); 9455682Smarkm break; 9555682Smarkm case SEEK_END: 9655682Smarkm sp->seek(sp, s->len + offset, SEEK_SET); 9755682Smarkm break; 9855682Smarkm default: 9955682Smarkm errno = EINVAL; 10055682Smarkm return -1; 10155682Smarkm } 10255682Smarkm return s->ptr - s->base; 10355682Smarkm} 10455682Smarkm 105233294Sstasstatic int 106233294Sstasemem_trunc(krb5_storage *sp, off_t offset) 107233294Sstas{ 108233294Sstas emem_storage *s = (emem_storage*)sp->data; 109233294Sstas /* 110233294Sstas * If offset is larget then current size, or current size is 111233294Sstas * shrunk more then half of the current size, adjust buffer. 112233294Sstas */ 113233294Sstas if (offset == 0) { 114233294Sstas free(s->base); 115233294Sstas s->size = 0; 116233294Sstas s->base = NULL; 117233294Sstas s->ptr = NULL; 118233294Sstas } else if ((size_t)offset > s->size || (s->size / 2) > (size_t)offset) { 119233294Sstas void *base; 120233294Sstas size_t off; 121233294Sstas off = s->ptr - s->base; 122233294Sstas base = realloc(s->base, offset); 123233294Sstas if(base == NULL) 124233294Sstas return ENOMEM; 125233294Sstas if ((size_t)offset > s->size) 126233294Sstas memset((char *)base + s->size, 0, offset - s->size); 127233294Sstas s->size = offset; 128233294Sstas s->base = base; 129233294Sstas s->ptr = (unsigned char *)base + off; 130233294Sstas } 131233294Sstas s->len = offset; 132233294Sstas if ((s->ptr - s->base) > offset) 133233294Sstas s->ptr = s->base + offset; 134233294Sstas return 0; 135233294Sstas} 136233294Sstas 137233294Sstas 13855682Smarkmstatic void 13955682Smarkmemem_free(krb5_storage *sp) 14055682Smarkm{ 14190926Snectar emem_storage *s = sp->data; 14290926Snectar memset(s->base, 0, s->len); 14390926Snectar free(s->base); 14455682Smarkm} 14555682Smarkm 146233294Sstas/** 147233294Sstas * Create a elastic (allocating) memory storage backend. Memory is 148233294Sstas * allocated on demand. Free returned krb5_storage with 149233294Sstas * krb5_storage_free(). 150233294Sstas * 151233294Sstas * @return A krb5_storage on success, or NULL on out of memory error. 152233294Sstas * 153233294Sstas * @ingroup krb5_storage 154233294Sstas * 155233294Sstas * @sa krb5_storage_from_mem() 156233294Sstas * @sa krb5_storage_from_readonly_mem() 157233294Sstas * @sa krb5_storage_from_fd() 158233294Sstas * @sa krb5_storage_from_data() 159233294Sstas */ 160233294Sstas 161233294SstasKRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL 16255682Smarkmkrb5_storage_emem(void) 16355682Smarkm{ 164233294Sstas krb5_storage *sp; 165233294Sstas emem_storage *s; 166233294Sstas 167233294Sstas sp = malloc(sizeof(krb5_storage)); 168178825Sdfr if (sp == NULL) 169178825Sdfr return NULL; 170233294Sstas 171233294Sstas s = malloc(sizeof(*s)); 172178825Sdfr if (s == NULL) { 173178825Sdfr free(sp); 174178825Sdfr return NULL; 175178825Sdfr } 17655682Smarkm sp->data = s; 17755682Smarkm sp->flags = 0; 178102644Snectar sp->eof_code = HEIM_ERR_EOF; 17955682Smarkm s->size = 1024; 18055682Smarkm s->base = malloc(s->size); 181178825Sdfr if (s->base == NULL) { 182178825Sdfr free(sp); 183178825Sdfr free(s); 184178825Sdfr return NULL; 185178825Sdfr } 18655682Smarkm s->len = 0; 18755682Smarkm s->ptr = s->base; 18855682Smarkm sp->fetch = emem_fetch; 18955682Smarkm sp->store = emem_store; 19055682Smarkm sp->seek = emem_seek; 191233294Sstas sp->trunc = emem_trunc; 19255682Smarkm sp->free = emem_free; 193233294Sstas sp->max_alloc = UINT_MAX/8; 19455682Smarkm return sp; 19555682Smarkm} 196