Home | History | Annotate | Line # | Download | only in modules
citrus_mapper_std.c revision 1.4
      1 /*	$NetBSD: citrus_mapper_std.c,v 1.4 2004/12/21 11:25:43 yamt 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.4 2004/12/21 11:25:43 yamt 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 #include <sys/queue.h>
     43 
     44 #include "citrus_namespace.h"
     45 #include "citrus_types.h"
     46 #include "citrus_bcs.h"
     47 #include "citrus_region.h"
     48 #include "citrus_mmap.h"
     49 #include "citrus_module.h"
     50 #include "citrus_hash.h"
     51 #include "citrus_mapper.h"
     52 #include "citrus_db.h"
     53 #include "citrus_db_hash.h"
     54 
     55 #include "citrus_mapper_std.h"
     56 #include "citrus_mapper_std_file.h"
     57 
     58 /* ---------------------------------------------------------------------- */
     59 
     60 _CITRUS_MAPPER_DECLS(mapper_std);
     61 _CITRUS_MAPPER_DEF_OPS(mapper_std);
     62 
     63 
     64 /* ---------------------------------------------------------------------- */
     65 
     66 int
     67 _citrus_mapper_std_mapper_getops(struct _citrus_mapper_ops *ops, size_t lenops,
     68 				 u_int32_t expected_version)
     69 {
     70 	if (expected_version<_CITRUS_MAPPER_ABI_VERSION || lenops<sizeof(*ops))
     71 		return (EINVAL);
     72 
     73 	memcpy(ops, &_citrus_mapper_std_mapper_ops,
     74 	       sizeof(_citrus_mapper_std_mapper_ops));
     75 
     76 	return (0);
     77 }
     78 
     79 /* ---------------------------------------------------------------------- */
     80 
     81 static int
     82 /*ARGSUSED*/
     83 rowcol_convert(struct _citrus_mapper_std * __restrict ms,
     84 	       _index_t * __restrict dst, _index_t src,
     85 	       void * __restrict ps)
     86 {
     87 	struct _citrus_mapper_std_rowcol *rc = &ms->ms_rowcol;
     88 	_index_t row, col, idx;
     89 	u_int32_t conv;
     90 
     91 	if (rc->rc_src_col_bits == 32) {
     92 		row = 0;
     93 		col = src;
     94 	} else {
     95 		row = src >> rc->rc_src_col_bits;
     96 		col = src & ((1U<<rc->rc_src_col_bits)-1);
     97 	}
     98 	if (row < rc->rc_src_row_begin || row > rc->rc_src_row_end ||
     99 	    col < rc->rc_src_col_begin || col > rc->rc_src_col_end) {
    100 		switch (rc->rc_oob_mode) {
    101 		case _CITRUS_MAPPER_STD_OOB_NONIDENTICAL:
    102 			*dst = rc->rc_dst_invalid;
    103 			return _MAPPER_CONVERT_NONIDENTICAL;
    104 		case _CITRUS_MAPPER_STD_OOB_ILSEQ:
    105 			return _MAPPER_CONVERT_ILSEQ;
    106 		default:
    107 			return _MAPPER_CONVERT_FATAL;
    108 		}
    109 	}
    110 
    111 	idx  =
    112 	    (row - rc->rc_src_row_begin)*rc->rc_src_col_width +
    113 	    (col - rc->rc_src_col_begin);
    114 
    115 	switch (rc->rc_dst_unit_bits) {
    116 	case 8:
    117 		conv = _region_peek8(&rc->rc_table, idx);
    118 		break;
    119 	case 16:
    120 		conv = be16toh(_region_peek16(&rc->rc_table, idx*2));
    121 		break;
    122 	case 32:
    123 		conv = be32toh(_region_peek32(&rc->rc_table, idx*4));
    124 		break;
    125 	}
    126 
    127 	if (conv == rc->rc_dst_invalid) {
    128 		*dst = rc->rc_dst_invalid;
    129 		return _MAPPER_CONVERT_NONIDENTICAL;
    130 	}
    131 	if (conv == rc->rc_dst_ilseq)
    132 		return _MAPPER_CONVERT_ILSEQ;
    133 
    134 	*dst = conv;
    135 
    136 	return _MAPPER_CONVERT_SUCCESS;
    137 }
    138 
    139 
    140 static int
    141 rowcol_init(struct _citrus_mapper_std *ms)
    142 {
    143 	int ret;
    144 	struct _citrus_mapper_std_rowcol *rc = &ms->ms_rowcol;
    145 	const struct _citrus_mapper_std_rowcol_info_x *rcx;
    146 	const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix;
    147 	struct _region r;
    148 	u_int64_t table_size;
    149 
    150 	ms->ms_convert = &rowcol_convert;
    151 	ms->ms_uninit = NULL;
    152 
    153 	/* get table region */
    154 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
    155 			      &rc->rc_table, NULL);
    156 	if (ret) {
    157 		if (ret==ENOENT)
    158 			ret = EFTYPE;
    159 		return ret;
    160 	}
    161 
    162 	/* get table information */
    163 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
    164 	if (ret) {
    165 		if (ret==ENOENT)
    166 			ret = EFTYPE;
    167 		return ret;
    168 	}
    169 	if (_region_size(&r) < sizeof(*rcx))
    170 		return EFTYPE;
    171 	rcx = _region_head(&r);
    172 
    173 	/* convert */
    174 #define CONV_ROWCOL(rc, rcx, elem)			\
    175 do {							\
    176 	(rc)->rc_##elem = be32toh((rcx)->rcx_##elem);	\
    177 } while (/*CONSTCOND*/0)
    178 	CONV_ROWCOL(rc, rcx, src_col_bits);
    179 	CONV_ROWCOL(rc, rcx, dst_invalid);
    180 	CONV_ROWCOL(rc, rcx, src_row_begin);
    181 	CONV_ROWCOL(rc, rcx, src_row_end);
    182 	CONV_ROWCOL(rc, rcx, src_col_begin);
    183 	CONV_ROWCOL(rc, rcx, src_col_end);
    184 	CONV_ROWCOL(rc, rcx, dst_unit_bits);
    185 
    186 	/* ilseq extension */
    187 	rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
    188 	rc->rc_dst_ilseq = rc->rc_dst_invalid;
    189 	ret = _db_lookup_by_s(ms->ms_db,
    190 			      _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ,
    191 			      &r, NULL);
    192 	if (ret && ret != ENOENT)
    193 		return ret;
    194 	if (_region_size(&r) < sizeof(*eix))
    195 		return EFTYPE;
    196 	if (ret == 0) {
    197 		eix = _region_head(&r);
    198 		rc->rc_oob_mode = be32toh(eix->eix_oob_mode);
    199 		rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq);
    200 	}
    201 	rc->rc_src_col_width = rc->rc_src_col_end - rc->rc_src_col_begin +1;
    202 
    203 	/* validation checks */
    204 	if (rc->rc_src_col_end < rc->rc_src_col_begin ||
    205 	    rc->rc_src_row_end < rc->rc_src_row_begin ||
    206 	    !(rc->rc_dst_unit_bits==8 || rc->rc_dst_unit_bits==16 ||
    207 	      rc->rc_dst_unit_bits==32) ||
    208 	    !(rc->rc_src_col_bits >= 0 && rc->rc_src_col_bits <= 32))
    209 		return EFTYPE;
    210 
    211 	/* calcurate expected table size */
    212 	table_size  = rc->rc_src_row_end - rc->rc_src_row_begin + 1;
    213 	table_size *= rc->rc_src_col_width;
    214 	table_size *= rc->rc_dst_unit_bits/8;
    215 
    216 	if (table_size > UINT32_MAX ||
    217 	    _region_size(&rc->rc_table) < table_size)
    218 		return EFTYPE;
    219 
    220 	return 0;
    221 }
    222 
    223 typedef int (*initfunc_t)(struct _citrus_mapper_std *);
    224 static const struct {
    225 	const char			*t_name;
    226 	initfunc_t			t_init;
    227 } types[] = {
    228 	{ _CITRUS_MAPPER_STD_TYPE_ROWCOL, &rowcol_init },
    229 };
    230 #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
    231 
    232 static int
    233 /*ARGSUSED*/
    234 _citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma,
    235 			       struct _citrus_mapper * __restrict cm,
    236 			       const char * __restrict curdir,
    237 			       const void * __restrict var, size_t lenvar,
    238 			       struct _citrus_mapper_traits * __restrict mt,
    239 			       size_t lenmt)
    240 {
    241 	char path[PATH_MAX];
    242 	const char *type;
    243 	int ret, id;
    244 	struct _citrus_mapper_std *ms;
    245 
    246 	/* set traits */
    247 	if (lenmt<sizeof(*mt)) {
    248 		ret = EINVAL;
    249 		goto err0;
    250 	}
    251 	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
    252 	mt->mt_state_size = 0;			/* stateless */
    253 
    254 	/* alloc mapper std structure */
    255 	ms = malloc(sizeof(*ms));
    256 	if (ms==NULL) {
    257 		ret = errno;
    258 		goto err0;
    259 	}
    260 
    261 	/* open mapper file */
    262 	snprintf(path, sizeof(path),
    263 		 "%s/%.*s", curdir, (int)lenvar, (const char *)var);
    264 	ret = _map_file(&ms->ms_file, path);
    265 	if (ret)
    266 		goto err1;
    267 
    268 	ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
    269 		       &_db_hash_std, NULL);
    270 	if (ret)
    271 		goto err2;
    272 
    273 	/* get mapper type */
    274 	ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
    275 				 &type, NULL);
    276 	if (ret) {
    277 		if (ret==ENOENT)
    278 			ret = EFTYPE;
    279 		goto err3;
    280 	}
    281 	for (id=0; id<NUM_OF_TYPES; id++)
    282 		if (_bcs_strcasecmp(type, types[id].t_name) == 0)
    283 			break;
    284 
    285 	if (id == NUM_OF_TYPES)
    286 		goto err3;
    287 
    288 	/* init the per-type structure */
    289 	ret = (*types[id].t_init)(ms);
    290 	if (ret)
    291 		goto err3;
    292 
    293 	cm->cm_closure = ms;
    294 
    295 	return 0;
    296 
    297 err3:
    298 	_db_close(ms->ms_db);
    299 err2:
    300 	_unmap_file(&ms->ms_file);
    301 err1:
    302 	free(ms);
    303 err0:
    304 	return ret;
    305 }
    306 
    307 static void
    308 /*ARGSUSED*/
    309 _citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
    310 {
    311 	struct _citrus_mapper_std *ms;
    312 
    313 	_DIAGASSERT(cm!=NULL & cm->cm_closure!=NULL);
    314 
    315 	ms = cm->cm_closure;
    316 	if (ms->ms_uninit)
    317 		(*ms->ms_uninit)(ms);
    318 	_db_close(ms->ms_db);
    319 	_unmap_file(&ms->ms_file);
    320 	free(ms);
    321 }
    322 
    323 static void
    324 /*ARGSUSED*/
    325 _citrus_mapper_std_mapper_init_state(struct _citrus_mapper * __restrict cm,
    326 				     void * __restrict ps)
    327 {
    328 }
    329 
    330 static int
    331 /*ARGSUSED*/
    332 _citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
    333 				  _index_t * __restrict dst, _index_t src,
    334 				  void * __restrict ps)
    335 {
    336 	struct _citrus_mapper_std *ms;
    337 
    338 	_DIAGASSERT(cm!=NULL && cm->cm_closure!=NULL);
    339 
    340 	ms = cm->cm_closure;
    341 
    342 	_DIAGASSERT(ms->ms_convert != NULL);
    343 
    344 	return (*ms->ms_convert)(ms, dst, src, ps);
    345 }
    346