xref: /netbsd-src/lib/libc/citrus/modules/citrus_mapper_std.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
1 /*	$NetBSD: citrus_mapper_std.c,v 1.1 2003/06/25 09:51:47 tshiozak Exp $	*/
2 
3 /*-
4  * Copyright (c)2003 Citrus Project,
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 #if defined(LIBC_SCCS) && !defined(lint)
31 __RCSID("$NetBSD: citrus_mapper_std.c,v 1.1 2003/06/25 09:51:47 tshiozak Exp $");
32 #endif /* LIBC_SCCS and not lint */
33 
34 #include <assert.h>
35 #include <errno.h>
36 #include <limits.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <stdint.h>
40 #include <string.h>
41 #include <sys/endian.h>
42 
43 #include "citrus_namespace.h"
44 #include "citrus_types.h"
45 #include "citrus_bcs.h"
46 #include "citrus_region.h"
47 #include "citrus_mmap.h"
48 #include "citrus_module.h"
49 #include "citrus_hash.h"
50 #include "citrus_mapper.h"
51 #include "citrus_db.h"
52 #include "citrus_db_hash.h"
53 
54 #include "citrus_mapper_std.h"
55 #include "citrus_mapper_std_file.h"
56 
57 /* ---------------------------------------------------------------------- */
58 
59 _CITRUS_MAPPER_DECLS(mapper_std);
60 _CITRUS_MAPPER_DEF_OPS(mapper_std);
61 
62 
63 /* ---------------------------------------------------------------------- */
64 
65 int
66 _citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops, size_t lenops,
67 				 u_int32_t expected_version)
68 {
69 	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
70 		return (EINVAL);
71 
72 	memcpy(ops, &_citrus_mapper_std_mapper_ops,
73 	       sizeof(_citrus_mapper_std_mapper_ops));
74 
75 	return (0);
76 }
77 
78 /* ---------------------------------------------------------------------- */
79 
80 static int
81 /*ARGSUSED*/
82 rowcol_convert(struct _citrus_mapper_std * __restrict ms,
83 	       _index_t * __restrict dst, _index_t src,
84 	       void * __restrict ps)
85 {
86 	struct _citrus_mapper_std_rowcol *rc = &ms->ms_rowcol;
87 	_index_t row, col, idx;
88 	u_int32_t conv;
89 
90 	if (rc->rc_src_col_bits == 32) {
91 		row = 0;
92 		col = src;
93 	} else {
94 		row = src >> rc->rc_src_col_bits;
95 		col = src & ((1U<<rc->rc_src_col_bits)-1);
96 	}
97 	if (row < rc->rc_src_row_begin || row > rc->rc_src_row_end ||
98 	    col < rc->rc_src_col_begin || col > rc->rc_src_col_end) {
99 		*dst = rc->rc_dst_invalid;
100 		return _MAPPER_CONVERT_INVAL;
101 	}
102 
103 	idx  =
104 	    (row - rc->rc_src_row_begin)*rc->rc_src_col_width +
105 	    (col - rc->rc_src_col_begin);
106 
107 	switch (rc->rc_dst_unit_bits) {
108 	case 8:
109 		conv = _region_peek8(&rc->rc_table, idx);
110 		break;
111 	case 16:
112 		conv = be16toh(_region_peek16(&rc->rc_table, idx*2));
113 		break;
114 	case 32:
115 		conv = be32toh(_region_peek32(&rc->rc_table, idx*4));
116 		break;
117 	}
118 
119 	if (conv == rc->rc_dst_invalid) {
120 		*dst = rc->rc_dst_invalid;
121 		return _MAPPER_CONVERT_INVAL;
122 	}
123 
124 	*dst = conv;
125 
126 	return _MAPPER_CONVERT_SUCCESS;
127 }
128 
129 
130 static int
131 rowcol_init(struct _citrus_mapper_std *ms)
132 {
133 	int ret;
134 	struct _citrus_mapper_std_rowcol *rc = &ms->ms_rowcol;
135 	const struct _citrus_mapper_std_rowcol_info_x *rcx;
136 	struct _region r;
137 	u_int64_t table_size;
138 
139 	ms->ms_convert = &rowcol_convert;
140 	ms->ms_uninit = NULL;
141 
142 	/* get table region */
143 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
144 			      &rc->rc_table, NULL);
145 	if (ret) {
146 		if (ret==ENOENT)
147 			ret = EFTYPE;
148 		return ret;
149 	}
150 
151 	/* get table information */
152 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
153 	if (ret) {
154 		if (ret==ENOENT)
155 			ret =EFTYPE;
156 		return ret;
157 	}
158 	if (_region_size(&r) < sizeof(*rcx))
159 		return EFTYPE;
160 	rcx = _region_head(&r);
161 
162 	/* convert */
163 #define CONV_ROWCOL(rc, rcx, elem)			\
164 do {							\
165 	(rc)->rc_##elem = be32toh((rcx)->rcx_##elem);	\
166 } while (/*CONSTCOND*/0)
167 	CONV_ROWCOL(rc, rcx, src_col_bits);
168 	CONV_ROWCOL(rc, rcx, dst_invalid);
169 	CONV_ROWCOL(rc, rcx, src_row_begin);
170 	CONV_ROWCOL(rc, rcx, src_row_end);
171 	CONV_ROWCOL(rc, rcx, src_col_begin);
172 	CONV_ROWCOL(rc, rcx, src_col_end);
173 	CONV_ROWCOL(rc, rcx, dst_unit_bits);
174 
175 	rc->rc_src_col_width = rc->rc_src_col_end - rc->rc_src_col_begin +1;
176 
177 	/* validation checks */
178 	if (rc->rc_src_col_end < rc->rc_src_col_begin ||
179 	    rc->rc_src_row_end < rc->rc_src_row_begin ||
180 	    !(rc->rc_dst_unit_bits==8 || rc->rc_dst_unit_bits==16 ||
181 	      rc->rc_dst_unit_bits==32) ||
182 	    !(rc->rc_src_col_bits >= 0 && rc->rc_src_col_bits <= 32))
183 		return EFTYPE;
184 
185 	/* calcurate expected table size */
186 	table_size  = rc->rc_src_row_end - rc->rc_src_row_begin + 1;
187 	table_size *= rc->rc_src_col_width;
188 	table_size *= rc->rc_dst_unit_bits/8;
189 
190 	if (table_size > UINT32_MAX ||
191 	    _region_size(&rc->rc_table) < table_size)
192 		return EFTYPE;
193 
194 	return 0;
195 }
196 
197 typedef int (*initfunc_t)(struct _citrus_mapper_std *);
198 static struct {
199 	const char			*t_name;
200 	initfunc_t			t_init;
201 } types[] = {
202 	{ _CITRUS_MAPPER_STD_TYPE_ROWCOL, &rowcol_init },
203 };
204 #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
205 
206 static int
207 /*ARGSUSED*/
208 _citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma,
209 			       struct _citrus_mapper * __restrict cm,
210 			       const char * __restrict curdir,
211 			       const void * __restrict var, size_t lenvar,
212 			       struct _citrus_mapper_traits * __restrict mt,
213 			       size_t lenmt)
214 {
215 	char path[PATH_MAX];
216 	const char *type;
217 	int ret, id;
218 	struct _citrus_mapper_std *ms;
219 
220 	/* set traits */
221 	if (lenmt<sizeof(*mt)) {
222 		ret = EINVAL;
223 		goto err0;
224 	}
225 	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
226 	mt->mt_state_size = 0;			/* stateless */
227 
228 	/* alloc mapper std structure */
229 	ms = malloc(sizeof(*ms));
230 	if (ms==NULL) {
231 		ret = errno;
232 		goto err0;
233 	}
234 
235 	/* open mapper file */
236 	snprintf(path, sizeof(path),
237 		 "%s/%.*s", curdir, (int)lenvar, (const char *)var);
238 	ret = _map_file(&ms->ms_file, path);
239 	if (ret)
240 		goto err1;
241 
242 	ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
243 		       &_db_hash_std, NULL);
244 	if (ret)
245 		goto err2;
246 
247 	/* get mapper type */
248 	ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
249 				 &type, NULL);
250 	if (ret) {
251 		if (ret==ENOENT)
252 			ret = EFTYPE;
253 		goto err3;
254 	}
255 	for (id=0; id<NUM_OF_TYPES; id++)
256 		if (_bcs_strcasecmp(type, types[id].t_name) == 0)
257 			break;
258 
259 	if (id == NUM_OF_TYPES)
260 		goto err3;
261 
262 	/* init the per-type structure */
263 	ret = (*types[id].t_init)(ms);
264 	if (ret)
265 		goto err3;
266 
267 	cm->cm_closure = ms;
268 
269 	return 0;
270 
271 err3:
272 	_db_close(ms->ms_db);
273 err2:
274 	_unmap_file(&ms->ms_file);
275 err1:
276 	free(ms);
277 err0:
278 	return ret;
279 }
280 
281 static void
282 /*ARGSUSED*/
283 _citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
284 {
285 	struct _citrus_mapper_std *ms;
286 
287 	_DIAGASSERT(cm!=NULL & cm->cm_closure!=NULL);
288 
289 	ms = cm->cm_closure;
290 	if (ms->ms_uninit)
291 		(*ms->ms_uninit)(ms);
292 	_db_close(ms->ms_db);
293 	_unmap_file(&ms->ms_file);
294 	free(ms);
295 }
296 
297 static void
298 /*ARGSUSED*/
299 _citrus_mapper_std_mapper_init_state(struct _citrus_mapper * __restrict cm,
300 				     void * __restrict ps)
301 {
302 }
303 
304 static int
305 /*ARGSUSED*/
306 _citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
307 				  _index_t * __restrict dst, _index_t src,
308 				  void * __restrict ps)
309 {
310 	struct _citrus_mapper_std *ms;
311 
312 	_DIAGASSERT(cm!=NULL && cm->cm_closure!=NULL);
313 
314 	ms = cm->cm_closure;
315 
316 	_DIAGASSERT(ms->ms_convert != NULL);
317 
318 	return (*ms->ms_convert)(ms, dst, src, ps);
319 }
320