1 /* $NetBSD: src/lib/libc/citrus/citrus_mapper.c,v 1.6 2004/12/30 05:05:01 christos Exp $ */
2 /* $DragonFly: src/lib/libc/citrus/citrus_mapper.c,v 1.2 2008/04/10 10:21:01 hasso Exp $ */
5 * Copyright (c)2003 Citrus Project,
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include "namespace.h"
32 #include <sys/types.h>
33 #include <sys/queue.h>
42 #include "un-namespace.h"
44 #include "libc_private.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
61 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
63 struct _citrus_mapper_area {
64 _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache;
69 * _citrus_mapper_create_area:
74 _citrus_mapper_create_area(
75 struct _citrus_mapper_area *__restrict *__restrict rma,
76 const char *__restrict area)
81 struct _citrus_mapper_area *ma;
84 _pthread_mutex_lock(&lock);
91 snprintf(path, PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
93 ret = stat(path, &st);
97 ma = malloc(sizeof(*ma));
102 ma->ma_dir = strdup(area);
103 if (ma->ma_dir == NULL) {
108 _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
114 _pthread_mutex_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, 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;
323 struct _citrus_mapper *cm;
327 _pthread_mutex_lock(&lock);
329 /* search in the cache */
330 hashval = hash_func(mapname);
331 _CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname,
341 /* search mapper entry */
342 ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf, PATH_MAX,
348 ret = mapper_open(ma, &cm, module, variable);
351 cm->cm_key = strdup(mapname);
352 if (cm->cm_key == NULL) {
355 _pthread_mutex_unlock(&lock);
360 /* insert to the cache */
362 _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
368 _pthread_mutex_unlock(&lock);
373 * _citrus_mapper_close:
374 * close the specified mapper.
377 _citrus_mapper_close(struct _citrus_mapper *cm)
381 _pthread_mutex_lock(&lock);
382 if (cm->cm_refcount == REFCOUNT_PERSISTENT)
384 if (cm->cm_refcount > 0) {
385 if (--cm->cm_refcount > 0)
387 _CITRUS_HASH_REMOVE(cm, cm_entry);
391 _pthread_mutex_unlock(&lock);
396 _pthread_mutex_unlock(&lock);
401 * _citrus_mapper_set_persistent:
402 * set persistent count.
405 _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
408 _pthread_mutex_lock(&lock);
409 cm->cm_refcount = REFCOUNT_PERSISTENT;
411 _pthread_mutex_unlock(&lock);