Home | History | Annotate | Line # | Download | only in modules
citrus_mapper_std.c revision 1.6
      1 /*	$NetBSD: citrus_mapper_std.c,v 1.6 2006/03/19 01:17:30 christos 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.6 2006/03/19 01:17:30 christos 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 <machine/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 	default:
    126 		return _MAPPER_CONVERT_FATAL;
    127 	}
    128 
    129 	if (conv == rc->rc_dst_invalid) {
    130 		*dst = rc->rc_dst_invalid;
    131 		return _MAPPER_CONVERT_NONIDENTICAL;
    132 	}
    133 	if (conv == rc->rc_dst_ilseq)
    134 		return _MAPPER_CONVERT_ILSEQ;
    135 
    136 	*dst = conv;
    137 
    138 	return _MAPPER_CONVERT_SUCCESS;
    139 }
    140 
    141 
    142 static int
    143 rowcol_init(struct _citrus_mapper_std *ms)
    144 {
    145 	int ret;
    146 	struct _citrus_mapper_std_rowcol *rc = &ms->ms_rowcol;
    147 	const struct _citrus_mapper_std_rowcol_info_x *rcx;
    148 	const struct _citrus_mapper_std_rowcol_ext_ilseq_info_x *eix;
    149 	struct _region r;
    150 	u_int64_t table_size;
    151 
    152 	ms->ms_convert = &rowcol_convert;
    153 	ms->ms_uninit = NULL;
    154 
    155 	/* get table region */
    156 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TABLE,
    157 			      &rc->rc_table, NULL);
    158 	if (ret) {
    159 		if (ret==ENOENT)
    160 			ret = EFTYPE;
    161 		return ret;
    162 	}
    163 
    164 	/* get table information */
    165 	ret = _db_lookup_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_INFO, &r, NULL);
    166 	if (ret) {
    167 		if (ret==ENOENT)
    168 			ret = EFTYPE;
    169 		return ret;
    170 	}
    171 	if (_region_size(&r) < sizeof(*rcx))
    172 		return EFTYPE;
    173 	rcx = _region_head(&r);
    174 
    175 	/* convert */
    176 #define CONV_ROWCOL(rc, rcx, elem)			\
    177 do {							\
    178 	(rc)->rc_##elem = be32toh((rcx)->rcx_##elem);	\
    179 } while (/*CONSTCOND*/0)
    180 	CONV_ROWCOL(rc, rcx, src_col_bits);
    181 	CONV_ROWCOL(rc, rcx, dst_invalid);
    182 	CONV_ROWCOL(rc, rcx, src_row_begin);
    183 	CONV_ROWCOL(rc, rcx, src_row_end);
    184 	CONV_ROWCOL(rc, rcx, src_col_begin);
    185 	CONV_ROWCOL(rc, rcx, src_col_end);
    186 	CONV_ROWCOL(rc, rcx, dst_unit_bits);
    187 
    188 	/* ilseq extension */
    189 	rc->rc_oob_mode = _CITRUS_MAPPER_STD_OOB_NONIDENTICAL;
    190 	rc->rc_dst_ilseq = rc->rc_dst_invalid;
    191 	ret = _db_lookup_by_s(ms->ms_db,
    192 			      _CITRUS_MAPPER_STD_SYM_ROWCOL_EXT_ILSEQ,
    193 			      &r, NULL);
    194 	if (ret && ret != ENOENT)
    195 		return ret;
    196 	if (_region_size(&r) < sizeof(*eix))
    197 		return EFTYPE;
    198 	if (ret == 0) {
    199 		eix = _region_head(&r);
    200 		rc->rc_oob_mode = be32toh(eix->eix_oob_mode);
    201 		rc->rc_dst_ilseq = be32toh(eix->eix_dst_ilseq);
    202 	}
    203 	rc->rc_src_col_width = rc->rc_src_col_end - rc->rc_src_col_begin +1;
    204 
    205 	/* validation checks */
    206 	if (rc->rc_src_col_end < rc->rc_src_col_begin ||
    207 	    rc->rc_src_row_end < rc->rc_src_row_begin ||
    208 	    !(rc->rc_dst_unit_bits==8 || rc->rc_dst_unit_bits==16 ||
    209 	      rc->rc_dst_unit_bits==32) ||
    210 	    !(rc->rc_src_col_bits >= 0 && rc->rc_src_col_bits <= 32))
    211 		return EFTYPE;
    212 
    213 	/* calcurate expected table size */
    214 	table_size  = rc->rc_src_row_end - rc->rc_src_row_begin + 1;
    215 	table_size *= rc->rc_src_col_width;
    216 	table_size *= rc->rc_dst_unit_bits/8;
    217 
    218 	if (table_size > UINT32_MAX ||
    219 	    _region_size(&rc->rc_table) < table_size)
    220 		return EFTYPE;
    221 
    222 	return 0;
    223 }
    224 
    225 typedef int (*initfunc_t)(struct _citrus_mapper_std *);
    226 static const struct {
    227 	const char			*t_name;
    228 	initfunc_t			t_init;
    229 } types[] = {
    230 	{ _CITRUS_MAPPER_STD_TYPE_ROWCOL, &rowcol_init },
    231 };
    232 #define NUM_OF_TYPES ((int)(sizeof(types)/sizeof(types[0])))
    233 
    234 static int
    235 /*ARGSUSED*/
    236 _citrus_mapper_std_mapper_init(struct _citrus_mapper_area *__restrict ma,
    237 			       struct _citrus_mapper * __restrict cm,
    238 			       const char * __restrict curdir,
    239 			       const void * __restrict var, size_t lenvar,
    240 			       struct _citrus_mapper_traits * __restrict mt,
    241 			       size_t lenmt)
    242 {
    243 	char path[PATH_MAX];
    244 	const char *type;
    245 	int ret, id;
    246 	struct _citrus_mapper_std *ms;
    247 
    248 	/* set traits */
    249 	if (lenmt<sizeof(*mt)) {
    250 		ret = EINVAL;
    251 		goto err0;
    252 	}
    253 	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
    254 	mt->mt_state_size = 0;			/* stateless */
    255 
    256 	/* alloc mapper std structure */
    257 	ms = malloc(sizeof(*ms));
    258 	if (ms==NULL) {
    259 		ret = errno;
    260 		goto err0;
    261 	}
    262 
    263 	/* open mapper file */
    264 	snprintf(path, sizeof(path),
    265 		 "%s/%.*s", curdir, (int)lenvar, (const char *)var);
    266 	ret = _map_file(&ms->ms_file, path);
    267 	if (ret)
    268 		goto err1;
    269 
    270 	ret = _db_open(&ms->ms_db, &ms->ms_file, _CITRUS_MAPPER_STD_MAGIC,
    271 		       &_db_hash_std, NULL);
    272 	if (ret)
    273 		goto err2;
    274 
    275 	/* get mapper type */
    276 	ret = _db_lookupstr_by_s(ms->ms_db, _CITRUS_MAPPER_STD_SYM_TYPE,
    277 				 &type, NULL);
    278 	if (ret) {
    279 		if (ret==ENOENT)
    280 			ret = EFTYPE;
    281 		goto err3;
    282 	}
    283 	for (id=0; id<NUM_OF_TYPES; id++)
    284 		if (_bcs_strcasecmp(type, types[id].t_name) == 0)
    285 			break;
    286 
    287 	if (id == NUM_OF_TYPES)
    288 		goto err3;
    289 
    290 	/* init the per-type structure */
    291 	ret = (*types[id].t_init)(ms);
    292 	if (ret)
    293 		goto err3;
    294 
    295 	cm->cm_closure = ms;
    296 
    297 	return 0;
    298 
    299 err3:
    300 	_db_close(ms->ms_db);
    301 err2:
    302 	_unmap_file(&ms->ms_file);
    303 err1:
    304 	free(ms);
    305 err0:
    306 	return ret;
    307 }
    308 
    309 static void
    310 /*ARGSUSED*/
    311 _citrus_mapper_std_mapper_uninit(struct _citrus_mapper *cm)
    312 {
    313 	struct _citrus_mapper_std *ms;
    314 
    315 	_DIAGASSERT(cm!=NULL & cm->cm_closure!=NULL);
    316 
    317 	ms = cm->cm_closure;
    318 	if (ms->ms_uninit)
    319 		(*ms->ms_uninit)(ms);
    320 	_db_close(ms->ms_db);
    321 	_unmap_file(&ms->ms_file);
    322 	free(ms);
    323 }
    324 
    325 static void
    326 /*ARGSUSED*/
    327 _citrus_mapper_std_mapper_init_state(struct _citrus_mapper * __restrict cm,
    328 				     void * __restrict ps)
    329 {
    330 }
    331 
    332 static int
    333 /*ARGSUSED*/
    334 _citrus_mapper_std_mapper_convert(struct _citrus_mapper * __restrict cm,
    335 				  _index_t * __restrict dst, _index_t src,
    336 				  void * __restrict ps)
    337 {
    338 	struct _citrus_mapper_std *ms;
    339 
    340 	_DIAGASSERT(cm!=NULL && cm->cm_closure!=NULL);
    341 
    342 	ms = cm->cm_closure;
    343 
    344 	_DIAGASSERT(ms->ms_convert != NULL);
    345 
    346 	return (*ms->ms_convert)(ms, dst, src, ps);
    347 }
    348