xref: /freebsd-src/lib/libiconv_modules/mapper_std/citrus_mapper_std.c (revision 2a63c3be158216222d89a073dcbd6a72ee4aab5a)
1*d2e53371SPedro F. Giffuni /*	$NetBSD: citrus_mapper_std.c,v 1.11 2018/06/11 18:03:38 kamil Exp $ */
2ad30f8e7SGabor Kovesdan 
3ad30f8e7SGabor Kovesdan /*-
45e53a4f9SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause
55e53a4f9SPedro F. Giffuni  *
6ad30f8e7SGabor Kovesdan  * Copyright (c)2003, 2006 Citrus Project,
7ad30f8e7SGabor Kovesdan  * All rights reserved.
8ad30f8e7SGabor Kovesdan  *
9ad30f8e7SGabor Kovesdan  * Redistribution and use in source and binary forms, with or without
10ad30f8e7SGabor Kovesdan  * modification, are permitted provided that the following conditions
11ad30f8e7SGabor Kovesdan  * are met:
12ad30f8e7SGabor Kovesdan  * 1. Redistributions of source code must retain the above copyright
13ad30f8e7SGabor Kovesdan  *    notice, this list of conditions and the following disclaimer.
14ad30f8e7SGabor Kovesdan  * 2. Redistributions in binary form must reproduce the above copyright
15ad30f8e7SGabor Kovesdan  *    notice, this list of conditions and the following disclaimer in the
16ad30f8e7SGabor Kovesdan  *    documentation and/or other materials provided with the distribution.
17ad30f8e7SGabor Kovesdan  *
18ad30f8e7SGabor Kovesdan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19ad30f8e7SGabor Kovesdan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20ad30f8e7SGabor Kovesdan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21ad30f8e7SGabor Kovesdan  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22ad30f8e7SGabor Kovesdan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23ad30f8e7SGabor Kovesdan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24ad30f8e7SGabor Kovesdan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25ad30f8e7SGabor Kovesdan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26ad30f8e7SGabor Kovesdan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27ad30f8e7SGabor Kovesdan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28ad30f8e7SGabor Kovesdan  * SUCH DAMAGE.
29ad30f8e7SGabor Kovesdan  */
30ad30f8e7SGabor Kovesdan 
31ad30f8e7SGabor Kovesdan #include <sys/cdefs.h>
32ad30f8e7SGabor Kovesdan #include <sys/endian.h>
33ad30f8e7SGabor Kovesdan #include <sys/queue.h>
34ad30f8e7SGabor Kovesdan 
35ad30f8e7SGabor Kovesdan #include <assert.h>
36ad30f8e7SGabor Kovesdan #include <errno.h>
37ad30f8e7SGabor Kovesdan #include <limits.h>
38ad30f8e7SGabor Kovesdan #include <stdint.h>
39ad30f8e7SGabor Kovesdan #include <stdio.h>
40ad30f8e7SGabor Kovesdan #include <stdlib.h>
41ad30f8e7SGabor Kovesdan #include <string.h>
42ad30f8e7SGabor Kovesdan 
43ad30f8e7SGabor Kovesdan #include "citrus_namespace.h"
44ad30f8e7SGabor Kovesdan #include "citrus_types.h"
45ad30f8e7SGabor Kovesdan #include "citrus_bcs.h"
46ad30f8e7SGabor Kovesdan #include "citrus_region.h"
47ad30f8e7SGabor Kovesdan #include "citrus_mmap.h"
48ad30f8e7SGabor Kovesdan #include "citrus_module.h"
49ad30f8e7SGabor Kovesdan #include "citrus_hash.h"
50ad30f8e7SGabor Kovesdan #include "citrus_mapper.h"
51ad30f8e7SGabor Kovesdan #include "citrus_db.h"
52ad30f8e7SGabor Kovesdan #include "citrus_db_hash.h"
53ad30f8e7SGabor Kovesdan 
54ad30f8e7SGabor Kovesdan #include "citrus_mapper_std.h"
55ad30f8e7SGabor Kovesdan #include "citrus_mapper_std_file.h"
56ad30f8e7SGabor Kovesdan 
57ad30f8e7SGabor Kovesdan /* ---------------------------------------------------------------------- */
58ad30f8e7SGabor Kovesdan 
59ad30f8e7SGabor Kovesdan _CITRUS_MAPPER_DECLS(mapper_std);
60ad30f8e7SGabor Kovesdan _CITRUS_MAPPER_DEF_OPS(mapper_std);
61ad30f8e7SGabor Kovesdan 
62ad30f8e7SGabor Kovesdan 
63ad30f8e7SGabor Kovesdan /* ---------------------------------------------------------------------- */
64ad30f8e7SGabor Kovesdan 
65ad30f8e7SGabor Kovesdan int
_citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops * ops)66ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops)
67ad30f8e7SGabor Kovesdan {
68ad30f8e7SGabor Kovesdan 
69ad30f8e7SGabor Kovesdan 	memcpy(ops, &_citrus_mapper_std_mapper_ops,
70ad30f8e7SGabor Kovesdan 	    sizeof(_citrus_mapper_std_mapper_ops));
71ad30f8e7SGabor Kovesdan 
72ad30f8e7SGabor Kovesdan 	return (0);
73ad30f8e7SGabor Kovesdan }
74ad30f8e7SGabor Kovesdan 
75ad30f8e7SGabor Kovesdan /* ---------------------------------------------------------------------- */
76ad30f8e7SGabor Kovesdan 
77ad30f8e7SGabor Kovesdan static int
78ad30f8e7SGabor Kovesdan /*ARGSUSED*/
rowcol_convert(struct _citrus_mapper_std * __restrict ms,_index_t * __restrict dst,_index_t src,void * __restrict ps __unused)79ad30f8e7SGabor Kovesdan rowcol_convert(struct _citrus_mapper_std * __restrict ms,
80ad30f8e7SGabor Kovesdan     _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
81ad30f8e7SGabor Kovesdan {
82ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_linear_zone *lz;
83ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_rowcol *rc;
84ad30f8e7SGabor Kovesdan 	_index_t idx = 0, n;
85ad30f8e7SGabor Kovesdan 	size_t i;
86ad30f8e7SGabor Kovesdan 	uint32_t conv;
87ad30f8e7SGabor Kovesdan 
88ad30f8e7SGabor Kovesdan 	/* ps may be unused */
89ad30f8e7SGabor Kovesdan 	rc = &ms->ms_rowcol;
90ad30f8e7SGabor Kovesdan 
91ad30f8e7SGabor Kovesdan 	for (i = rc->rc_src_rowcol_len * rc->rc_src_rowcol_bits,
92ad30f8e7SGabor Kovesdan 	    lz = &rc->rc_src_rowcol[0]; i > 0; ++lz) {
93ad30f8e7SGabor Kovesdan 		i -= rc->rc_src_rowcol_bits;
94ad30f8e7SGabor Kovesdan 		n = (src >> i) & rc->rc_src_rowcol_mask;
95ad30f8e7SGabor Kovesdan 		if (n < lz->begin || n > lz->end) {
96ad30f8e7SGabor Kovesdan 			switch (rc->rc_oob_mode) {
97ad30f8e7SGabor Kovesdan 			case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
98ad30f8e7SGabor Kovesdan 				*dst = rc->rc_dst_invalid;
99ad30f8e7SGabor Kovesdan 				return (_MAPPER_CONVERT_NONIDENTICAL);
100ad30f8e7SGabor Kovesdan 			case _CITRUS_MAPPER_STD_OOB_ILSEQ:
101ad30f8e7SGabor Kovesdan 				return (_MAPPER_CONVERT_ILSEQ);
102ad30f8e7SGabor Kovesdan 			default:
103ad30f8e7SGabor Kovesdan 				return (_MAPPER_CONVERT_FATAL);
104ad30f8e7SGabor Kovesdan 			}
105ad30f8e7SGabor Kovesdan 		}
106ad30f8e7SGabor Kovesdan 		idx = idx * lz->width + n - lz->begin;
107ad30f8e7SGabor Kovesdan 	}
108ad30f8e7SGabor Kovesdan 	switch (rc->rc_dst_unit_bits) {
109ad30f8e7SGabor Kovesdan 	case 8:
110ad30f8e7SGabor Kovesdan 		conv = _region_peek8(&rc->rc_table, idx);
111ad30f8e7SGabor Kovesdan 		break;
112ad30f8e7SGabor Kovesdan 	case 16:
113ad30f8e7SGabor Kovesdan 		conv = be16toh(_region_peek16(&rc->rc_table, idx*2));
114ad30f8e7SGabor Kovesdan 		break;
115ad30f8e7SGabor Kovesdan 	case 32:
116ad30f8e7SGabor Kovesdan 		conv = be32toh(_region_peek32(&rc->rc_table, idx*4));
117ad30f8e7SGabor Kovesdan 		break;
118ad30f8e7SGabor Kovesdan 	default:
119ad30f8e7SGabor Kovesdan 		return (_MAPPER_CONVERT_FATAL);
120ad30f8e7SGabor Kovesdan 	}
121ad30f8e7SGabor Kovesdan 
122ad30f8e7SGabor Kovesdan 	if (conv == rc->rc_dst_invalid) {
123ad30f8e7SGabor Kovesdan 		*dst = rc->rc_dst_invalid;
124ad30f8e7SGabor Kovesdan 		return (_MAPPER_CONVERT_NONIDENTICAL);
125ad30f8e7SGabor Kovesdan 	}
126ad30f8e7SGabor Kovesdan 	if (conv == rc->rc_dst_ilseq)
127ad30f8e7SGabor Kovesdan 		return (_MAPPER_CONVERT_ILSEQ);
128ad30f8e7SGabor Kovesdan 
129ad30f8e7SGabor Kovesdan 	*dst = conv;
130ad30f8e7SGabor Kovesdan 
131ad30f8e7SGabor Kovesdan 	return (_MAPPER_CONVERT_SUCCESS);
132ad30f8e7SGabor Kovesdan }
133ad30f8e7SGabor Kovesdan 
134ad30f8e7SGabor Kovesdan static __inline int
set_linear_zone(struct _citrus_mapper_std_linear_zone * lz,uint32_t begin,uint32_t end)135ad30f8e7SGabor Kovesdan set_linear_zone(struct _citrus_mapper_std_linear_zone *lz,
136ad30f8e7SGabor Kovesdan     uint32_t begin, uint32_t end)
137ad30f8e7SGabor Kovesdan {
138ad30f8e7SGabor Kovesdan 
139ad30f8e7SGabor Kovesdan 	if (begin > end)
140ad30f8e7SGabor Kovesdan 		return (EFTYPE);
141ad30f8e7SGabor Kovesdan 
142ad30f8e7SGabor Kovesdan 	lz->begin = begin;
143ad30f8e7SGabor Kovesdan 	lz->end = end;
144ad30f8e7SGabor Kovesdan 	lz->width= end - begin + 1;
145ad30f8e7SGabor Kovesdan 
146ad30f8e7SGabor Kovesdan 	return (0);
147ad30f8e7SGabor Kovesdan }
148ad30f8e7SGabor Kovesdan 
149ad30f8e7SGabor Kovesdan static __inline int
rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol * rc,struct _region * r)150ad30f8e7SGabor Kovesdan rowcol_parse_variable_compat(struct _citrus_mapper_std_rowcol *rc,
151ad30f8e7SGabor Kovesdan     struct _region *r)
152ad30f8e7SGabor Kovesdan {
153ad30f8e7SGabor Kovesdan 	const struct _citrus_mapper_std_rowcol_info_compat_x *rcx;
154ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_linear_zone *lz;
155ad30f8e7SGabor Kovesdan 	uint32_t m, n;
156ad30f8e7SGabor Kovesdan 	int ret;
157ad30f8e7SGabor Kovesdan 
158ad30f8e7SGabor Kovesdan 	rcx = _region_head(r);
159ad30f8e7SGabor Kovesdan 
160ad30f8e7SGabor Kovesdan 	rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
161ad30f8e7SGabor Kovesdan 	rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
162ad30f8e7SGabor Kovesdan 	m = be32toh(rcx->rcx_src_col_bits);
163*d2e53371SPedro F. Giffuni 	n = 1U << (m - 1);
164ad30f8e7SGabor Kovesdan 	n |= n - 1;
165ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol_bits = m;
166ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol_mask = n;
167ad30f8e7SGabor Kovesdan 
168ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol = malloc(2 *
169ad30f8e7SGabor Kovesdan 	    sizeof(*rc->rc_src_rowcol));
170ad30f8e7SGabor Kovesdan 	if (rc->rc_src_rowcol == NULL)
171ad30f8e7SGabor Kovesdan 		return (ENOMEM);
172ad30f8e7SGabor Kovesdan 	lz = rc->rc_src_rowcol;
173ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol_len = 1;
174ad30f8e7SGabor Kovesdan 	m = be32toh(rcx->rcx_src_row_begin);
175ad30f8e7SGabor Kovesdan 	n = be32toh(rcx->rcx_src_row_end);
176ad30f8e7SGabor Kovesdan 	if (m + n > 0) {
177ad30f8e7SGabor Kovesdan 		ret = set_linear_zone(lz, m, n);
1789ca40936STijl Coosemans 		if (ret != 0) {
1799ca40936STijl Coosemans 			free(rc->rc_src_rowcol);
1809ca40936STijl Coosemans 			rc->rc_src_rowcol = NULL;
181ad30f8e7SGabor Kovesdan 			return (ret);
1829ca40936STijl Coosemans 		}
183ad30f8e7SGabor Kovesdan 		++rc->rc_src_rowcol_len, ++lz;
184ad30f8e7SGabor Kovesdan 	}
185ad30f8e7SGabor Kovesdan 	m = be32toh(rcx->rcx_src_col_begin);
186ad30f8e7SGabor Kovesdan 	n = be32toh(rcx->rcx_src_col_end);
187ad30f8e7SGabor Kovesdan 
188ad30f8e7SGabor Kovesdan 	return (set_linear_zone(lz, m, n));
189ad30f8e7SGabor Kovesdan }
190ad30f8e7SGabor Kovesdan 
191ad30f8e7SGabor Kovesdan static __inline int
rowcol_parse_variable(struct _citrus_mapper_std_rowcol * rc,struct _region * r)192ad30f8e7SGabor Kovesdan rowcol_parse_variable(struct _citrus_mapper_std_rowcol *rc,
193ad30f8e7SGabor Kovesdan     struct _region *r)
194ad30f8e7SGabor Kovesdan {
195ad30f8e7SGabor Kovesdan 	const struct _citrus_mapper_std_rowcol_info_x *rcx;
196ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_linear_zone *lz;
197ad30f8e7SGabor Kovesdan 	size_t i;
198ad30f8e7SGabor Kovesdan 	uint32_t m, n;
199ad30f8e7SGabor Kovesdan 	int ret;
200ad30f8e7SGabor Kovesdan 
201ad30f8e7SGabor Kovesdan 	rcx = _region_head(r);
202ad30f8e7SGabor Kovesdan 
203ad30f8e7SGabor Kovesdan 	rc->rc_dst_invalid = be32toh(rcx->rcx_dst_invalid);
204ad30f8e7SGabor Kovesdan 	rc->rc_dst_unit_bits = be32toh(rcx->rcx_dst_unit_bits);
205ad30f8e7SGabor Kovesdan 
206ad30f8e7SGabor Kovesdan 	m = be32toh(rcx->rcx_src_rowcol_bits);
207ad30f8e7SGabor Kovesdan 	n = 1 << (m - 1);
208ad30f8e7SGabor Kovesdan 	n |= n - 1;
209ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol_bits = m;
210ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol_mask = n;
211ad30f8e7SGabor Kovesdan 
212ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol_len = be32toh(rcx->rcx_src_rowcol_len);
213ad30f8e7SGabor Kovesdan 	if (rc->rc_src_rowcol_len > _CITRUS_MAPPER_STD_ROWCOL_MAX)
214ad30f8e7SGabor Kovesdan 		return (EFTYPE);
215ad30f8e7SGabor Kovesdan 	rc->rc_src_rowcol = malloc(rc->rc_src_rowcol_len *
216ad30f8e7SGabor Kovesdan 	    sizeof(*rc->rc_src_rowcol));
217ad30f8e7SGabor Kovesdan 	if (rc->rc_src_rowcol == NULL)
218ad30f8e7SGabor Kovesdan 		return (ENOMEM);
219ad30f8e7SGabor Kovesdan 	for (i = 0, lz = rc->rc_src_rowcol;
220ad30f8e7SGabor Kovesdan 	    i < rc->rc_src_rowcol_len; ++i, ++lz) {
221ad30f8e7SGabor Kovesdan 		m = be32toh(rcx->rcx_src_rowcol[i].begin),
222ad30f8e7SGabor Kovesdan 		n = be32toh(rcx->rcx_src_rowcol[i].end);
223ad30f8e7SGabor Kovesdan 		ret = set_linear_zone(lz, m, n);
224ad30f8e7SGabor Kovesdan 		if (ret != 0) {
225ad30f8e7SGabor Kovesdan 			free(rc->rc_src_rowcol);
226ad30f8e7SGabor Kovesdan 			rc->rc_src_rowcol = NULL;
227ad30f8e7SGabor Kovesdan 			return (ret);
228ad30f8e7SGabor Kovesdan 		}
229ad30f8e7SGabor Kovesdan 	}
230ad30f8e7SGabor Kovesdan 	return (0);
231ad30f8e7SGabor Kovesdan }
232ad30f8e7SGabor Kovesdan 
233ad30f8e7SGabor Kovesdan static void
rowcol_uninit(struct _citrus_mapper_std * ms)234ad30f8e7SGabor Kovesdan rowcol_uninit(struct _citrus_mapper_std *ms)
235ad30f8e7SGabor Kovesdan {
236ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_rowcol *rc;
237ad30f8e7SGabor Kovesdan 
238ad30f8e7SGabor Kovesdan 	rc = &ms->ms_rowcol;
239ad30f8e7SGabor Kovesdan 	free(rc->rc_src_rowcol);
240ad30f8e7SGabor Kovesdan }
241ad30f8e7SGabor Kovesdan 
242ad30f8e7SGabor Kovesdan static int
rowcol_init(struct _citrus_mapper_std * ms)243ad30f8e7SGabor Kovesdan rowcol_init(struct _citrus_mapper_std *ms)
244ad30f8e7SGabor Kovesdan {
245ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_linear_zone *lz;
246ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std_rowcol *rc;
247ad30f8e7SGabor Kovesdan 	const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix;
248ad30f8e7SGabor Kovesdan 	struct _region r;
249ad30f8e7SGabor Kovesdan 	uint64_t table_size;
250ad30f8e7SGabor Kovesdan 	size_t i;
251ad30f8e7SGabor Kovesdan 	int ret;
252ad30f8e7SGabor Kovesdan 
253ad30f8e7SGabor Kovesdan 	ms->ms_convert = &rowcol_convert;
254ad30f8e7SGabor Kovesdan 	ms->ms_uninit = &rowcol_uninit;
255ad30f8e7SGabor Kovesdan 	rc = &ms->ms_rowcol;
256ad30f8e7SGabor Kovesdan 
257ad30f8e7SGabor Kovesdan 	/* get table region */
258ad30f8e7SGabor Kovesdan 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
259ad30f8e7SGabor Kovesdan 	    &rc->rc_table, NULL);
260ad30f8e7SGabor Kovesdan 	if (ret) {
261ad30f8e7SGabor Kovesdan 		if (ret == ENOENT)
262ad30f8e7SGabor Kovesdan 			ret = EFTYPE;
263ad30f8e7SGabor Kovesdan 		return (ret);
264ad30f8e7SGabor Kovesdan 	}
265ad30f8e7SGabor Kovesdan 
266ad30f8e7SGabor Kovesdan 	/* get table information */
267ad30f8e7SGabor Kovesdan 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
268ad30f8e7SGabor Kovesdan 	if (ret) {
269ad30f8e7SGabor Kovesdan 		if (ret == ENOENT)
270ad30f8e7SGabor Kovesdan 			ret = EFTYPE;
271ad30f8e7SGabor Kovesdan 		return (ret);
272ad30f8e7SGabor Kovesdan 	}
273ad30f8e7SGabor Kovesdan 	switch (_region_size(&r)) {
274ad30f8e7SGabor Kovesdan 	case _CITRUS_MAPPER_STD_ROWCOL_INFO_COMPAT_SIZE:
275ad30f8e7SGabor Kovesdan 		ret = rowcol_parse_variable_compat(rc, &r);
276ad30f8e7SGabor Kovesdan 		break;
277ad30f8e7SGabor Kovesdan 	case _CITRUS_MAPPER_STD_ROWCOL_INFO_SIZE:
278ad30f8e7SGabor Kovesdan 		ret = rowcol_parse_variable(rc, &r);
279ad30f8e7SGabor Kovesdan 		break;
280ad30f8e7SGabor Kovesdan 	default:
281ad30f8e7SGabor Kovesdan 		return (EFTYPE);
282ad30f8e7SGabor Kovesdan 	}
283ad30f8e7SGabor Kovesdan 	if (ret != 0)
284ad30f8e7SGabor Kovesdan 		return (ret);
285ad30f8e7SGabor Kovesdan 	/* sanity check */
286ad30f8e7SGabor Kovesdan 	switch (rc->rc_src_rowcol_bits) {
287ad30f8e7SGabor Kovesdan 	case 8: case 16: case 32:
288ad30f8e7SGabor Kovesdan 		if (rc->rc_src_rowcol_len <= 32 / rc->rc_src_rowcol_bits)
289ad30f8e7SGabor Kovesdan 			break;
290ad30f8e7SGabor Kovesdan 	/*FALLTHROUGH*/
291ad30f8e7SGabor Kovesdan 	default:
292ad30f8e7SGabor Kovesdan 		return (EFTYPE);
293ad30f8e7SGabor Kovesdan 	}
294ad30f8e7SGabor Kovesdan 
295ad30f8e7SGabor Kovesdan 	/* ilseq extension */
296ad30f8e7SGabor Kovesdan 	rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
297ad30f8e7SGabor Kovesdan 	rc->rc_dst_ilseq = rc->rc_dst_invalid;
298ad30f8e7SGabor Kovesdan 	ret = _db_lookup_by_s(ms->ms_db,
299ad30f8e7SGabor Kovesdan 	    _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ, &r, NULL);
300ad30f8e7SGabor Kovesdan 	if (ret && ret != ENOENT)
301ad30f8e7SGabor Kovesdan 		return (ret);
302ad30f8e7SGabor Kovesdan 	if (_region_size(&r) < sizeof(*eix))
303ad30f8e7SGabor Kovesdan 		return (EFTYPE);
304ad30f8e7SGabor Kovesdan 	if (ret == 0) {
305ad30f8e7SGabor Kovesdan 		eix = _region_head(&r);
306ad30f8e7SGabor Kovesdan 		rc->rc_oob_mode = be32toh(eix->eix_oob_mode);
307ad30f8e7SGabor Kovesdan 		rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq);
308ad30f8e7SGabor Kovesdan 	}
309ad30f8e7SGabor Kovesdan 
310ad30f8e7SGabor Kovesdan 	/* calcurate expected table size */
311ad30f8e7SGabor Kovesdan 	i = rc->rc_src_rowcol_len;
312ad30f8e7SGabor Kovesdan 	lz = &rc->rc_src_rowcol[--i];
313ad30f8e7SGabor Kovesdan 	table_size = lz->width;
314ad30f8e7SGabor Kovesdan 	while (i > 0) {
315ad30f8e7SGabor Kovesdan 		lz = &rc->rc_src_rowcol[--i];
316ad30f8e7SGabor Kovesdan 		table_size *= lz->width;
317ad30f8e7SGabor Kovesdan 	}
318ad30f8e7SGabor Kovesdan 	table_size *= rc->rc_dst_unit_bits/8;
319ad30f8e7SGabor Kovesdan 
320ad30f8e7SGabor Kovesdan 	if (table_size > UINT32_MAX ||
321ad30f8e7SGabor Kovesdan 	    _region_size(&rc->rc_table) < table_size)
322ad30f8e7SGabor Kovesdan 		return (EFTYPE);
323ad30f8e7SGabor Kovesdan 
324ad30f8e7SGabor Kovesdan 	return (0);
325ad30f8e7SGabor Kovesdan }
326ad30f8e7SGabor Kovesdan 
327ad30f8e7SGabor Kovesdan typedef int (*initfunc_t)(struct _citrus_mapper_std *);
328ad30f8e7SGabor Kovesdan static const struct {
329ad30f8e7SGabor Kovesdan 	initfunc_t			 t_init;
330ad30f8e7SGabor Kovesdan 	const char			*t_name;
331ad30f8e7SGabor Kovesdan } types[] = {
332ad30f8e7SGabor Kovesdan 	{ &rowcol_init, _CITRUS_MAPPER_STD_TYPE_ROWCOL },
333ad30f8e7SGabor Kovesdan };
334ad30f8e7SGabor Kovesdan #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
335ad30f8e7SGabor Kovesdan 
336ad30f8e7SGabor Kovesdan static int
337ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_init(struct _citrus_mapper_area * __restrict ma __unused,struct _citrus_mapper * __restrict cm,const char * __restrict curdir,const void * __restrict var,size_t lenvar,struct _citrus_mapper_traits * __restrict mt,size_t lenmt)338ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
339ad30f8e7SGabor Kovesdan     struct _citrus_mapper * __restrict cm, const char * __restrict curdir,
340ad30f8e7SGabor Kovesdan     const void * __restrict var, size_t lenvar,
341ad30f8e7SGabor Kovesdan     struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
342ad30f8e7SGabor Kovesdan {
343ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std *ms;
344ad30f8e7SGabor Kovesdan 	char path[PATH_MAX];
345ad30f8e7SGabor Kovesdan 	const char *type;
346ad30f8e7SGabor Kovesdan 	int id, ret;
347ad30f8e7SGabor Kovesdan 
348ad30f8e7SGabor Kovesdan 	/* set traits */
349ad30f8e7SGabor Kovesdan 	if (lenmt < sizeof(*mt)) {
350ad30f8e7SGabor Kovesdan 		ret = EINVAL;
351ad30f8e7SGabor Kovesdan 		goto err0;
352ad30f8e7SGabor Kovesdan 	}
353ad30f8e7SGabor Kovesdan 	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
354ad30f8e7SGabor Kovesdan 	mt->mt_state_size = 0;			/* stateless */
355ad30f8e7SGabor Kovesdan 
356ad30f8e7SGabor Kovesdan 	/* alloc mapper std structure */
357ad30f8e7SGabor Kovesdan 	ms = malloc(sizeof(*ms));
358ad30f8e7SGabor Kovesdan 	if (ms == NULL) {
359ad30f8e7SGabor Kovesdan 		ret = errno;
360ad30f8e7SGabor Kovesdan 		goto err0;
361ad30f8e7SGabor Kovesdan 	}
362ad30f8e7SGabor Kovesdan 
363ad30f8e7SGabor Kovesdan 	/* open mapper file */
364ad30f8e7SGabor Kovesdan 	snprintf(path, sizeof(path), "%s/%.*s", curdir, (int)lenvar,
365ad30f8e7SGabor Kovesdan 	    (const char *)var);
366ad30f8e7SGabor Kovesdan 	ret = _map_file(&ms->ms_file, path);
367ad30f8e7SGabor Kovesdan 	if (ret)
368ad30f8e7SGabor Kovesdan 		goto err1;
369ad30f8e7SGabor Kovesdan 
370ad30f8e7SGabor Kovesdan 	ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
371ad30f8e7SGabor Kovesdan 	    &_db_hash_std, NULL);
372ad30f8e7SGabor Kovesdan 	if (ret)
373ad30f8e7SGabor Kovesdan 		goto err2;
374ad30f8e7SGabor Kovesdan 
375ad30f8e7SGabor Kovesdan 	/* get mapper type */
376ad30f8e7SGabor Kovesdan 	ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
377ad30f8e7SGabor Kovesdan 	    &type, NULL);
378ad30f8e7SGabor Kovesdan 	if (ret) {
379ad30f8e7SGabor Kovesdan 		if (ret == ENOENT)
380ad30f8e7SGabor Kovesdan 			ret = EFTYPE;
381ad30f8e7SGabor Kovesdan 		goto err3;
382ad30f8e7SGabor Kovesdan 	}
383ad30f8e7SGabor Kovesdan 	for (id = 0; id < NUM_OF_TYPES; id++)
384ad30f8e7SGabor Kovesdan 		if (_bcs_strcasecmp(type, types[id].t_name) == 0)
385ad30f8e7SGabor Kovesdan 			break;
386ad30f8e7SGabor Kovesdan 
387ad30f8e7SGabor Kovesdan 	if (id == NUM_OF_TYPES)
388ad30f8e7SGabor Kovesdan 		goto err3;
389ad30f8e7SGabor Kovesdan 
390ad30f8e7SGabor Kovesdan 	/* init the per-type structure */
391ad30f8e7SGabor Kovesdan 	ret = (*types[id].t_init)(ms);
392ad30f8e7SGabor Kovesdan 	if (ret)
393ad30f8e7SGabor Kovesdan 		goto err3;
394ad30f8e7SGabor Kovesdan 
395ad30f8e7SGabor Kovesdan 	cm->cm_closure = ms;
396ad30f8e7SGabor Kovesdan 
397ad30f8e7SGabor Kovesdan 	return (0);
398ad30f8e7SGabor Kovesdan 
399ad30f8e7SGabor Kovesdan err3:
400ad30f8e7SGabor Kovesdan 	_db_close(ms->ms_db);
401ad30f8e7SGabor Kovesdan err2:
402ad30f8e7SGabor Kovesdan 	_unmap_file(&ms->ms_file);
403ad30f8e7SGabor Kovesdan err1:
404ad30f8e7SGabor Kovesdan 	free(ms);
405ad30f8e7SGabor Kovesdan err0:
406ad30f8e7SGabor Kovesdan 	return (ret);
407ad30f8e7SGabor Kovesdan }
408ad30f8e7SGabor Kovesdan 
409ad30f8e7SGabor Kovesdan static void
410ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_uninit(struct _citrus_mapper * cm)411ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
412ad30f8e7SGabor Kovesdan {
413ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std *ms;
414ad30f8e7SGabor Kovesdan 
415ad30f8e7SGabor Kovesdan 	ms = cm->cm_closure;
416ad30f8e7SGabor Kovesdan 	if (ms->ms_uninit)
417ad30f8e7SGabor Kovesdan 		(*ms->ms_uninit)(ms);
418ad30f8e7SGabor Kovesdan 	_db_close(ms->ms_db);
419ad30f8e7SGabor Kovesdan 	_unmap_file(&ms->ms_file);
420ad30f8e7SGabor Kovesdan 	free(ms);
421ad30f8e7SGabor Kovesdan }
422ad30f8e7SGabor Kovesdan 
423ad30f8e7SGabor Kovesdan static void
424ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_init_state(void)425ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_init_state(void)
426ad30f8e7SGabor Kovesdan {
427ad30f8e7SGabor Kovesdan 
428ad30f8e7SGabor Kovesdan }
429ad30f8e7SGabor Kovesdan 
430ad30f8e7SGabor Kovesdan static int
431ad30f8e7SGabor Kovesdan /*ARGSUSED*/
_citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,_index_t * __restrict dst,_index_t src,void * __restrict ps)432ad30f8e7SGabor Kovesdan _citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
433ad30f8e7SGabor Kovesdan     _index_t * __restrict dst, _index_t src, void * __restrict ps)
434ad30f8e7SGabor Kovesdan {
435ad30f8e7SGabor Kovesdan 	struct _citrus_mapper_std *ms;
436ad30f8e7SGabor Kovesdan 
437ad30f8e7SGabor Kovesdan 	ms = cm->cm_closure;
438ad30f8e7SGabor Kovesdan 	return ((*ms->ms_convert)(ms, dst, src, ps));
439ad30f8e7SGabor Kovesdan }
440