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