1 /* $NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
2 /* $DragonFly: src/lib/libc/citrus/citrus_esdb.c,v 1.2 2008/04/10 10:21:01 hasso Exp $ */
6 * Copyright (c)2003 Citrus Project,
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 #include <sys/types.h>
40 #include "citrus_namespace.h"
41 #include "citrus_types.h"
42 #include "citrus_bcs.h"
43 #include "citrus_region.h"
44 #include "citrus_memstream.h"
45 #include "citrus_mmap.h"
46 #include "citrus_lookup.h"
47 #include "citrus_db.h"
48 #include "citrus_db_hash.h"
49 #include "citrus_esdb.h"
50 #include "citrus_esdb_file.h"
52 #define ESDB_DIR "esdb.dir"
53 #define ESDB_ALIAS "esdb.alias"
57 * resolve encoding scheme name aliases.
60 _citrus_esdb_alias(const char *esname
, char *buf
, size_t bufsize
)
62 return _lookup_alias(_PATH_ESDB
"/" ESDB_ALIAS
, esname
, buf
, bufsize
,
69 * external representation -> local structure.
72 conv_esdb(struct _citrus_esdb
*esdb
, struct _region
*fr
)
75 struct _citrus_db
*db
;
76 uint32_t version
, num_charsets
, csid
, i
, tmp
;
81 ret
= _db_open(&db
, fr
, _CITRUS_ESDB_MAGIC
, &_db_hash_std
, NULL
);
86 ret
= _db_lookup32_by_s(db
, _CITRUS_ESDB_SYM_VERSION
, &version
, NULL
);
99 /* get encoding/variable */
100 ret
= _db_lookupstr_by_s(db
, _CITRUS_ESDB_SYM_ENCODING
, &str
, NULL
);
103 esdb
->db_encname
= strdup(str
);
104 if (esdb
->db_encname
== NULL
) {
109 esdb
->db_len_variable
= 0;
110 esdb
->db_variable
= NULL
;
111 ret
= _db_lookupstr_by_s(db
, _CITRUS_ESDB_SYM_VARIABLE
, &str
, NULL
);
113 esdb
->db_len_variable
= strlen(str
)+1;
114 esdb
->db_variable
= strdup(str
);
115 if (esdb
->db_variable
== NULL
) {
119 } else if (ret
!= ENOENT
)
122 /* get number of charsets */
123 ret
= _db_lookup32_by_s(db
, _CITRUS_ESDB_SYM_NUM_CHARSETS
,
124 &num_charsets
, NULL
);
127 esdb
->db_num_charsets
= num_charsets
;
129 /* get invalid character */
130 ret
= _db_lookup32_by_s(db
, _CITRUS_ESDB_SYM_INVALID
, &tmp
, NULL
);
132 esdb
->db_use_invalid
= 1;
133 esdb
->db_invalid
= tmp
;
134 } else if (ret
== ENOENT
)
135 esdb
->db_use_invalid
= 0;
140 esdb
->db_charsets
= malloc(num_charsets
* sizeof(*esdb
->db_charsets
));
141 if (esdb
->db_charsets
== NULL
) {
145 for (i
= 0; i
< num_charsets
; i
++) {
146 snprintf(buf
, sizeof(buf
),
147 _CITRUS_ESDB_SYM_CSID_PREFIX
"%d", i
);
148 ret
= _db_lookup32_by_s(db
, buf
, &csid
, NULL
);
151 esdb
->db_charsets
[i
].ec_csid
= csid
;
153 snprintf(buf
, sizeof(buf
),
154 _CITRUS_ESDB_SYM_CSNAME_PREFIX
"%d", i
);
155 ret
= _db_lookupstr_by_s(db
, buf
, &str
, NULL
);
158 esdb
->db_charsets
[i
].ec_csname
= strdup(str
);
159 if (esdb
->db_charsets
[i
].ec_csname
== NULL
) {
170 free(esdb
->db_charsets
[i
- 1].ec_csname
);
171 free(esdb
->db_charsets
);
173 free(esdb
->db_variable
);
175 free(esdb
->db_encname
);
189 _citrus_esdb_open(struct _citrus_esdb
*db
, const char *esname
)
192 const char *realname
, *encfile
;
193 char buf1
[PATH_MAX
], buf2
[PATH_MAX
], path
[PATH_MAX
];
196 _DIAGASSERT(esname
!= NULL
);
198 snprintf(path
, sizeof(path
), "%s/%s", _PATH_ESDB
, ESDB_ALIAS
);
199 realname
= _lookup_alias(path
, esname
, buf1
, sizeof(buf1
),
200 _LOOKUP_CASE_IGNORE
);
202 snprintf(path
, sizeof(path
), "%s/%s", _PATH_ESDB
, ESDB_DIR
);
203 encfile
= _lookup_simple(path
, realname
, buf2
, sizeof(buf2
),
204 _LOOKUP_CASE_IGNORE
);
209 snprintf(path
, sizeof(path
), "%s/%s", _PATH_ESDB
, encfile
);
210 ret
= _map_file(&fr
, path
);
214 ret
= conv_esdb(db
, &fr
);
222 * _citrus_esdb_close:
226 _citrus_esdb_close(struct _citrus_esdb
*db
)
230 _DIAGASSERT(db
!= NULL
);
231 _DIAGASSERT(db
->db_num_charsets
== 0 || db
->db_charsets
!= NULL
);
233 for (i
= 0; i
< db
->db_num_charsets
; i
++)
234 free(db
->db_charsets
[i
].ec_csname
);
235 db
->db_num_charsets
= 0;
236 free(db
->db_charsets
); db
->db_charsets
= NULL
;
237 free(db
->db_encname
); db
->db_encname
= NULL
;
238 db
->db_len_variable
= 0;
239 free(db
->db_variable
); db
->db_variable
= NULL
;
243 * _citrus_esdb_free_list:
247 _citrus_esdb_free_list(char **list
, size_t num
)
251 for (i
= 0; i
< num
; i
++)
257 * _citrus_esdb_get_list:
261 _citrus_esdb_get_list(char ***rlist
, size_t *rnum
)
266 struct _citrus_lookup
*cla
, *cld
;
272 ret
= _lookup_seq_open(&cla
, _PATH_ESDB
"/" ESDB_ALIAS
,
273 _LOOKUP_CASE_IGNORE
);
277 ret
= _lookup_seq_open(&cld
, _PATH_ESDB
"/" ESDB_DIR
,
278 _LOOKUP_CASE_IGNORE
);
282 /* count number of entries */
283 num
= _lookup_get_num_entries(cla
) + _lookup_get_num_entries(cld
);
285 _lookup_seq_rewind(cla
);
286 _lookup_seq_rewind(cld
);
288 /* allocate list pointer space */
289 list
= malloc(num
* sizeof(char *));
296 /* get alias entries */
297 while ((ret
= _lookup_seq_next(cla
, &key
, NULL
)) == 0) {
298 snprintf(buf
, sizeof(buf
), "%.*s",
299 (int)_region_size(&key
),
300 (const char *)_region_head(&key
));
301 _bcs_convert_to_lower(buf
);
302 list
[num
] = strdup(buf
);
303 if (list
[num
] == NULL
) {
311 /* get dir entries */
312 while ((ret
= _lookup_seq_next(cld
, &key
, NULL
)) == 0) {
313 /* check duplicated entry */
314 snprintf(buf
, sizeof(buf
), "%.*s",
315 (int)_region_size(&key
),
316 (const char *)_region_head(&key
));
317 _bcs_convert_to_lower(buf
);
318 ret
= _lookup_seq_lookup(cla
, buf
, NULL
);
323 list
[num
] = strdup(buf
);
324 if (list
[num
] == NULL
) {
335 q
= realloc(list
, num
* sizeof(char *));
345 _citrus_esdb_free_list(list
, num
);
346 _lookup_seq_close(cld
);
348 _lookup_seq_close(cla
);