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