1/*
2 * Copyright (c) 1997 - 2000, 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "krb5_locl.h"
35#include "store-int.h"
36
37typedef struct mem_storage{
38    unsigned char *base;
39    size_t size;
40    unsigned char *ptr;
41}mem_storage;
42
43static ssize_t
44mem_fetch(krb5_storage *sp, void *data, size_t size)
45{
46    mem_storage *s = (mem_storage*)sp->data;
47    if(size > (size_t)(s->base + s->size - s->ptr))
48	size = s->base + s->size - s->ptr;
49    memmove(data, s->ptr, size);
50    sp->seek(sp, size, SEEK_CUR);
51    return size;
52}
53
54static ssize_t
55mem_store(krb5_storage *sp, const void *data, size_t size)
56{
57    mem_storage *s = (mem_storage*)sp->data;
58    if(size > (size_t)(s->base + s->size - s->ptr))
59	size = s->base + s->size - s->ptr;
60    memmove(s->ptr, data, size);
61    sp->seek(sp, size, SEEK_CUR);
62    return size;
63}
64
65static ssize_t
66mem_no_store(krb5_storage *sp, const void *data, size_t size)
67{
68    return -1;
69}
70
71static off_t
72mem_seek(krb5_storage *sp, off_t offset, int whence)
73{
74    mem_storage *s = (mem_storage*)sp->data;
75    switch(whence){
76    case SEEK_SET:
77	if((size_t)offset > s->size)
78	    offset = s->size;
79	if(offset < 0)
80	    offset = 0;
81	s->ptr = s->base + offset;
82	break;
83    case SEEK_CUR:
84	return sp->seek(sp, s->ptr - s->base + offset, SEEK_SET);
85    case SEEK_END:
86	return sp->seek(sp, s->size + offset, SEEK_SET);
87    default:
88	errno = EINVAL;
89	return -1;
90    }
91    return s->ptr - s->base;
92}
93
94static int
95mem_trunc(krb5_storage *sp, off_t offset)
96{
97    mem_storage *s = (mem_storage*)sp->data;
98    if((size_t)offset > s->size)
99	return ERANGE;
100    s->size = offset;
101    if ((s->ptr - s->base) > offset)
102	s->ptr = s->base + offset;
103    return 0;
104}
105
106static int
107mem_no_trunc(krb5_storage *sp, off_t offset)
108{
109    return EINVAL;
110}
111
112/**
113 * Create a fixed size memory storage block
114 *
115 * @return A krb5_storage on success, or NULL on out of memory error.
116 *
117 * @ingroup krb5_storage
118 *
119 * @sa krb5_storage_mem()
120 * @sa krb5_storage_from_readonly_mem()
121 * @sa krb5_storage_from_data()
122 * @sa krb5_storage_from_fd()
123 */
124
125KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL
126krb5_storage_from_mem(void *buf, size_t len)
127{
128    krb5_storage *sp = malloc(sizeof(krb5_storage));
129    mem_storage *s;
130    if(sp == NULL)
131	return NULL;
132    s = malloc(sizeof(*s));
133    if(s == NULL) {
134	free(sp);
135	return NULL;
136    }
137    sp->data = s;
138    sp->flags = 0;
139    sp->eof_code = HEIM_ERR_EOF;
140    s->base = buf;
141    s->size = len;
142    s->ptr = buf;
143    sp->fetch = mem_fetch;
144    sp->store = mem_store;
145    sp->seek = mem_seek;
146    sp->trunc = mem_trunc;
147    sp->free = NULL;
148    sp->max_alloc = UINT_MAX/8;
149    return sp;
150}
151
152/**
153 * Create a fixed size memory storage block
154 *
155 * @return A krb5_storage on success, or NULL on out of memory error.
156 *
157 * @ingroup krb5_storage
158 *
159 * @sa krb5_storage_mem()
160 * @sa krb5_storage_from_mem()
161 * @sa krb5_storage_from_readonly_mem()
162 * @sa krb5_storage_from_fd()
163 */
164
165KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL
166krb5_storage_from_data(krb5_data *data)
167{
168    return krb5_storage_from_mem(data->data, data->length);
169}
170
171/**
172 * Create a fixed size memory storage block that is read only
173 *
174 * @return A krb5_storage on success, or NULL on out of memory error.
175 *
176 * @ingroup krb5_storage
177 *
178 * @sa krb5_storage_mem()
179 * @sa krb5_storage_from_mem()
180 * @sa krb5_storage_from_data()
181 * @sa krb5_storage_from_fd()
182 */
183
184KRB5_LIB_FUNCTION krb5_storage * KRB5_LIB_CALL
185krb5_storage_from_readonly_mem(const void *buf, size_t len)
186{
187    krb5_storage *sp = malloc(sizeof(krb5_storage));
188    mem_storage *s;
189    if(sp == NULL)
190	return NULL;
191    s = malloc(sizeof(*s));
192    if(s == NULL) {
193	free(sp);
194	return NULL;
195    }
196    sp->data = s;
197    sp->flags = 0;
198    sp->eof_code = HEIM_ERR_EOF;
199    s->base = rk_UNCONST(buf);
200    s->size = len;
201    s->ptr = rk_UNCONST(buf);
202    sp->fetch = mem_fetch;
203    sp->store = mem_no_store;
204    sp->seek = mem_seek;
205    sp->trunc = mem_no_trunc;
206    sp->free = NULL;
207    sp->max_alloc = UINT_MAX/8;
208    return sp;
209}
210