1 /* $NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
4 * Copyright (c)2003 Citrus Project,
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
29 #include <sys/cdefs.h>
30 #if defined(LIBC_SCCS) && !defined(lint)
31 __RCSID("$NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp $");
32 #endif /* LIBC_SCCS and not lint */
34 #include "namespace.h"
35 #include "reentrant.h"
42 #include <sys/types.h>
44 #include <sys/queue.h>
46 #include "citrus_namespace.h"
47 #include "citrus_types.h"
48 #include "citrus_region.h"
49 #include "citrus_memstream.h"
50 #include "citrus_bcs.h"
51 #include "citrus_mmap.h"
52 #include "citrus_module.h"
53 #include "citrus_hash.h"
54 #include "citrus_mapper.h"
56 #define _CITRUS_MAPPER_DIR "mapper.dir"
58 #define CM_HASH_SIZE 101
59 #define REFCOUNT_PERSISTENT -1
62 static rwlock_t lock
= RWLOCK_INITIALIZER
;
65 struct _citrus_mapper_area
{
66 _CITRUS_HASH_HEAD(, _citrus_mapper
, CM_HASH_SIZE
) ma_cache
;
71 * _citrus_mapper_create_area:
76 _citrus_mapper_create_area(
77 struct _citrus_mapper_area
*__restrict
*__restrict rma
,
78 const char *__restrict area
)
83 struct _citrus_mapper_area
*ma
;
92 snprintf(path
, (size_t)PATH_MAX
, "%s/%s", area
, _CITRUS_MAPPER_DIR
);
94 ret
= stat(path
, &st
);
98 ma
= malloc(sizeof(*ma
));
103 ma
->ma_dir
= strdup(area
);
104 if (ma
->ma_dir
== NULL
) {
109 _CITRUS_HASH_INIT(&ma
->ma_cache
, CM_HASH_SIZE
);
114 rwlock_unlock(&lock
);
121 * lookup_mapper_entry:
122 * lookup mapper.dir entry in the specified directory.
124 * line format of iconv.dir file:
126 * mapper : mapper name.
127 * module : mapper module name.
128 * arg : argument for the module (generally, description file name)
132 lookup_mapper_entry(const char *dir
, const char *mapname
,
133 void *linebuf
, size_t linebufsize
,
134 const char **module
, const char **variable
)
137 struct _memstream ms
;
144 /* create mapper.dir path */
145 snprintf(path
, (size_t)PATH_MAX
, "%s/%s", dir
, _CITRUS_MAPPER_DIR
);
147 /* open read stream */
148 ret
= _map_file(&r
, path
);
152 _memstream_bind(&ms
, &r
);
154 /* search the line matching to the map name */
155 cp
= _memstream_matchline(&ms
, mapname
, &len
, 0);
160 if (!len
|| len
>linebufsize
-1) {
166 /* get module name */
168 cq
= _bcs_skip_nonws_len(cp
, &len
);
169 strlcpy(p
, cp
, (size_t)(cq
-cp
+1));
174 cp
= _bcs_skip_ws_len(cq
, &len
);
175 strlcpy(p
, cp
, len
+1);
186 * simply close a mapper. (without handling hash)
189 mapper_close(struct _citrus_mapper
*cm
)
194 (*cm
->cm_ops
->mo_uninit
)(cm
);
197 _citrus_unload_module(cm
->cm_module
);
205 * simply open a mapper. (without handling hash)
208 mapper_open(struct _citrus_mapper_area
*__restrict ma
,
209 struct _citrus_mapper
* __restrict
* __restrict rcm
,
210 const char * __restrict module
,
211 const char * __restrict variable
)
214 struct _citrus_mapper
*cm
;
215 _citrus_mapper_getops_t getops
;
217 /* initialize mapper handle */
218 cm
= malloc(sizeof(*cm
));
222 cm
->cm_module
= NULL
;
224 cm
->cm_closure
= NULL
;
225 cm
->cm_traits
= NULL
;
230 ret
= _citrus_load_module(&cm
->cm_module
, module
);
235 getops
= (_citrus_mapper_getops_t
)
236 _citrus_find_getops(cm
->cm_module
, module
, "mapper");
241 cm
->cm_ops
= malloc(sizeof(*cm
->cm_ops
));
246 ret
= (*getops
)(cm
->cm_ops
, sizeof(*cm
->cm_ops
),
247 _CITRUS_MAPPER_ABI_VERSION
);
251 if (!cm
->cm_ops
->mo_init
||
252 !cm
->cm_ops
->mo_uninit
||
253 !cm
->cm_ops
->mo_convert
||
254 !cm
->cm_ops
->mo_init_state
)
257 /* allocate traits structure */
258 cm
->cm_traits
= malloc(sizeof(*cm
->cm_traits
));
259 if (cm
->cm_traits
== NULL
) {
263 /* initialize the mapper */
264 ret
= (*cm
->cm_ops
->mo_init
)(ma
, cm
, ma
->ma_dir
,
265 (const void *)variable
,
267 cm
->cm_traits
, sizeof(*cm
->cm_traits
));
281 * _citrus_mapper_open_direct:
285 _citrus_mapper_open_direct(struct _citrus_mapper_area
*__restrict ma
,
286 struct _citrus_mapper
* __restrict
* __restrict rcm
,
287 const char * __restrict module
,
288 const char * __restrict variable
)
290 return mapper_open(ma
, rcm
, module
, variable
);
297 hash_func(const char *key
)
299 return _string_hash_func(key
, CM_HASH_SIZE
);
306 match_func(struct _citrus_mapper
*cm
, const char *key
)
308 return strcmp(cm
->cm_key
, key
);
312 * _citrus_mapper_open:
313 * open a mapper with looking up "mapper.dir".
316 _citrus_mapper_open(struct _citrus_mapper_area
*__restrict ma
,
317 struct _citrus_mapper
* __restrict
* __restrict rcm
,
318 const char * __restrict mapname
)
321 char linebuf
[PATH_MAX
];
322 const char *module
, *variable
= NULL
;
323 struct _citrus_mapper
*cm
;
326 rwlock_wrlock(&lock
);
328 /* search in the cache */
329 hashval
= hash_func(mapname
);
330 _CITRUS_HASH_SEARCH(&ma
->ma_cache
, cm
, cm_entry
, match_func
, mapname
,
340 /* search mapper entry */
341 ret
= lookup_mapper_entry(ma
->ma_dir
, mapname
, linebuf
,
342 (size_t)PATH_MAX
, &module
, &variable
);
347 ret
= mapper_open(ma
, &cm
, module
, variable
);
350 cm
->cm_key
= strdup(mapname
);
351 if (cm
->cm_key
== NULL
) {
353 rwlock_unlock(&lock
);
358 /* insert to the cache */
360 _CITRUS_HASH_INSERT(&ma
->ma_cache
, cm
, cm_entry
, hashval
);
365 rwlock_unlock(&lock
);
370 * _citrus_mapper_close:
371 * close the specified mapper.
374 _citrus_mapper_close(struct _citrus_mapper
*cm
)
377 rwlock_wrlock(&lock
);
378 if (cm
->cm_refcount
== REFCOUNT_PERSISTENT
)
380 if (cm
->cm_refcount
> 0) {
381 if (--cm
->cm_refcount
> 0)
383 _CITRUS_HASH_REMOVE(cm
, cm_entry
);
386 rwlock_unlock(&lock
);
390 rwlock_unlock(&lock
);
395 * _citrus_mapper_set_persistent:
396 * set persistent count.
399 _citrus_mapper_set_persistent(struct _citrus_mapper
* __restrict cm
)
401 rwlock_wrlock(&lock
);
402 cm
->cm_refcount
= REFCOUNT_PERSISTENT
;
403 rwlock_unlock(&lock
);