1 /* $NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung 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_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $");
32 #endif /* LIBC_SCCS and not lint */
34 #include "namespace.h"
42 #include <sys/types.h>
44 #include "citrus_namespace.h"
45 #include "citrus_types.h"
46 #include "citrus_bcs.h"
47 #include "citrus_region.h"
48 #include "citrus_memstream.h"
49 #include "citrus_mmap.h"
50 #include "citrus_lookup.h"
51 #include "citrus_db.h"
52 #include "citrus_db_hash.h"
53 #include "citrus_esdb.h"
54 #include "citrus_esdb_file.h"
56 #define ESDB_DIR "esdb.dir"
57 #define ESDB_ALIAS "esdb.alias"
61 * resolve encoding scheme name aliases.
64 _citrus_esdb_alias(const char *esname
, char *buf
, size_t bufsize
)
66 return _lookup_alias(_PATH_ESDB
"/" ESDB_ALIAS
, esname
, buf
, bufsize
,
73 * external representation -> local structure.
76 conv_esdb(struct _citrus_esdb
*esdb
, struct _region
*fr
)
79 struct _citrus_db
*db
;
80 uint32_t version
, num_charsets
, csid
, i
, tmp
;
85 ret
= _db_open(&db
, fr
, _CITRUS_ESDB_MAGIC
, &_db_hash_std
, NULL
);
90 ret
= _db_lookup32_by_s(db
, _CITRUS_ESDB_SYM_VERSION
, &version
, NULL
);
103 /* get encoding/variable */
104 ret
= _db_lookupstr_by_s(db
, _CITRUS_ESDB_SYM_ENCODING
, &str
, NULL
);
107 esdb
->db_encname
= strdup(str
);
108 if (esdb
->db_encname
== NULL
) {
113 esdb
->db_len_variable
= 0;
114 esdb
->db_variable
= NULL
;
115 ret
= _db_lookupstr_by_s(db
, _CITRUS_ESDB_SYM_VARIABLE
, &str
, NULL
);
117 esdb
->db_len_variable
= strlen(str
)+1;
118 esdb
->db_variable
= strdup(str
);
119 if (esdb
->db_variable
== NULL
) {
123 } else if (ret
!= ENOENT
)
126 /* get number of charsets */
127 ret
= _db_lookup32_by_s(db
, _CITRUS_ESDB_SYM_NUM_CHARSETS
,
128 &num_charsets
, NULL
);
131 esdb
->db_num_charsets
= num_charsets
;
133 /* get invalid character */
134 ret
= _db_lookup32_by_s(db
, _CITRUS_ESDB_SYM_INVALID
, &tmp
, NULL
);
136 esdb
->db_use_invalid
= 1;
137 esdb
->db_invalid
= tmp
;
138 } else if (ret
== ENOENT
)
139 esdb
->db_use_invalid
= 0;
144 esdb
->db_charsets
= malloc(num_charsets
* sizeof(*esdb
->db_charsets
));
145 if (esdb
->db_charsets
== NULL
) {
149 for (i
= 0; i
< num_charsets
; i
++) {
150 snprintf(buf
, sizeof(buf
),
151 _CITRUS_ESDB_SYM_CSID_PREFIX
"%d", i
);
152 ret
= _db_lookup32_by_s(db
, buf
, &csid
, NULL
);
155 esdb
->db_charsets
[i
].ec_csid
= csid
;
157 snprintf(buf
, sizeof(buf
),
158 _CITRUS_ESDB_SYM_CSNAME_PREFIX
"%d", i
);
159 ret
= _db_lookupstr_by_s(db
, buf
, &str
, NULL
);
162 esdb
->db_charsets
[i
].ec_csname
= strdup(str
);
163 if (esdb
->db_charsets
[i
].ec_csname
== NULL
) {
174 free(esdb
->db_charsets
[i
- 1].ec_csname
);
175 free(esdb
->db_charsets
);
177 free(esdb
->db_variable
);
179 free(esdb
->db_encname
);
193 _citrus_esdb_open(struct _citrus_esdb
*db
, const char *esname
)
196 const char *realname
, *encfile
;
197 char buf1
[PATH_MAX
], buf2
[PATH_MAX
], path
[PATH_MAX
];
200 _DIAGASSERT(esname
!= NULL
);
202 snprintf(path
, sizeof(path
), "%s/%s", _PATH_ESDB
, ESDB_ALIAS
);
203 realname
= _lookup_alias(path
, esname
, buf1
, sizeof(buf1
),
204 _LOOKUP_CASE_IGNORE
);
206 snprintf(path
, sizeof(path
), "%s/%s", _PATH_ESDB
, ESDB_DIR
);
207 encfile
= _lookup_simple(path
, realname
, buf2
, sizeof(buf2
),
208 _LOOKUP_CASE_IGNORE
);
213 snprintf(path
, sizeof(path
), "%s/%s", _PATH_ESDB
, encfile
);
214 ret
= _map_file(&fr
, path
);
218 ret
= conv_esdb(db
, &fr
);
226 * _citrus_esdb_close:
230 _citrus_esdb_close(struct _citrus_esdb
*db
)
234 _DIAGASSERT(db
!= NULL
);
235 _DIAGASSERT(db
->db_num_charsets
== 0 || db
->db_charsets
!= NULL
);
237 for (i
= 0; i
< db
->db_num_charsets
; i
++)
238 free(db
->db_charsets
[i
].ec_csname
);
239 db
->db_num_charsets
= 0;
240 free(db
->db_charsets
); db
->db_charsets
= NULL
;
241 free(db
->db_encname
); db
->db_encname
= NULL
;
242 db
->db_len_variable
= 0;
243 free(db
->db_variable
); db
->db_variable
= NULL
;
247 * _citrus_esdb_free_list:
251 _citrus_esdb_free_list(char **list
, size_t num
)
255 for (i
= 0; i
< num
; i
++)
261 * _citrus_esdb_get_list:
265 _citrus_esdb_get_list(char ***rlist
, size_t *rnum
)
270 struct _citrus_lookup
*cla
, *cld
;
276 ret
= _lookup_seq_open(&cla
, _PATH_ESDB
"/" ESDB_ALIAS
,
277 _LOOKUP_CASE_IGNORE
);
281 ret
= _lookup_seq_open(&cld
, _PATH_ESDB
"/" ESDB_DIR
,
282 _LOOKUP_CASE_IGNORE
);
286 /* count number of entries */
287 num
= _lookup_get_num_entries(cla
) + _lookup_get_num_entries(cld
);
289 _lookup_seq_rewind(cla
);
290 _lookup_seq_rewind(cld
);
292 /* allocate list pointer space */
293 list
= malloc(num
* sizeof(char *));
300 /* get alias entries */
301 while ((ret
= _lookup_seq_next(cla
, &key
, NULL
)) == 0) {
302 snprintf(buf
, sizeof(buf
), "%.*s",
303 (int)_region_size(&key
),
304 (const char *)_region_head(&key
));
305 _bcs_convert_to_lower(buf
);
306 list
[num
] = strdup(buf
);
307 if (list
[num
] == NULL
) {
315 /* get dir entries */
316 while ((ret
= _lookup_seq_next(cld
, &key
, NULL
)) == 0) {
317 /* check duplicated entry */
318 snprintf(buf
, sizeof(buf
), "%.*s",
319 (int)_region_size(&key
),
320 (const char *)_region_head(&key
));
321 _bcs_convert_to_lower(buf
);
322 ret
= _lookup_seq_lookup(cla
, buf
, NULL
);
327 list
[num
] = strdup(buf
);
328 if (list
[num
] == NULL
) {
339 q
= realloc(list
, num
* sizeof(char *));
349 _citrus_esdb_free_list(list
, num
);
350 _lookup_seq_close(cld
);
352 _lookup_seq_close(cla
);