| @@ -1,388 +1,388 @@ | | | @@ -1,388 +1,388 @@ |
1 | /* $NetBSD: citrus_csmapper.c,v 1.11 2011/11/20 07:43:52 tnozaki Exp $ */ | | 1 | /* $NetBSD: citrus_csmapper.c,v 1.12 2019/10/09 23:23:41 christos Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c)2003 Citrus Project, | | 4 | * Copyright (c)2003 Citrus Project, |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | | 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 | | 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | | 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 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 | | 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 | | 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 | | 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
26 | * SUCH DAMAGE. | | 26 | * SUCH DAMAGE. |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | #include <sys/cdefs.h> | | 29 | #include <sys/cdefs.h> |
30 | #if defined(LIBC_SCCS) && !defined(lint) | | 30 | #if defined(LIBC_SCCS) && !defined(lint) |
31 | __RCSID("$NetBSD: citrus_csmapper.c,v 1.11 2011/11/20 07:43:52 tnozaki Exp $"); | | 31 | __RCSID("$NetBSD: citrus_csmapper.c,v 1.12 2019/10/09 23:23:41 christos Exp $"); |
32 | #endif /* LIBC_SCCS and not lint */ | | 32 | #endif /* LIBC_SCCS and not lint */ |
33 | | | 33 | |
34 | #include "namespace.h" | | 34 | #include "namespace.h" |
35 | #include "reentrant.h" | | 35 | #include "reentrant.h" |
36 | #include <assert.h> | | 36 | #include <assert.h> |
37 | #include <stdio.h> | | 37 | #include <stdio.h> |
38 | #include <stdlib.h> | | 38 | #include <stdlib.h> |
39 | #include <string.h> | | 39 | #include <string.h> |
40 | #include <errno.h> | | 40 | #include <errno.h> |
41 | #include <limits.h> | | 41 | #include <limits.h> |
42 | #include <paths.h> | | 42 | #include <paths.h> |
43 | #include <sys/types.h> | | 43 | #include <sys/types.h> |
44 | #include <sys/queue.h> | | 44 | #include <sys/queue.h> |
45 | | | 45 | |
46 | #include "citrus_namespace.h" | | 46 | #include "citrus_namespace.h" |
47 | #include "citrus_types.h" | | 47 | #include "citrus_types.h" |
48 | #include "citrus_bcs.h" | | 48 | #include "citrus_bcs.h" |
49 | #include "citrus_region.h" | | 49 | #include "citrus_region.h" |
50 | #include "citrus_memstream.h" | | 50 | #include "citrus_memstream.h" |
51 | #include "citrus_mmap.h" | | 51 | #include "citrus_mmap.h" |
52 | #include "citrus_module.h" | | 52 | #include "citrus_module.h" |
53 | #include "citrus_hash.h" | | 53 | #include "citrus_hash.h" |
54 | #include "citrus_mapper.h" | | 54 | #include "citrus_mapper.h" |
55 | #include "citrus_csmapper.h" | | 55 | #include "citrus_csmapper.h" |
56 | #include "citrus_pivot_file.h" | | 56 | #include "citrus_pivot_file.h" |
57 | #include "citrus_db.h" | | 57 | #include "citrus_db.h" |
58 | #include "citrus_db_hash.h" | | 58 | #include "citrus_db_hash.h" |
59 | #include "citrus_lookup.h" | | 59 | #include "citrus_lookup.h" |
60 | | | 60 | |
61 | #ifdef _REENTRANT | | 61 | #ifdef _REENTRANT |
62 | static rwlock_t lock = RWLOCK_INITIALIZER; | | 62 | static rwlock_t lock = RWLOCK_INITIALIZER; |
63 | #endif | | 63 | #endif |
64 | static struct _citrus_mapper_area *maparea = NULL; | | 64 | static struct _citrus_mapper_area *maparea = NULL; |
65 | | | 65 | |
66 | #define CS_ALIAS _PATH_CSMAPPER "/charset.alias" | | 66 | #define CS_ALIAS _PATH_CSMAPPER "/charset.alias" |
67 | #define CS_PIVOT _PATH_CSMAPPER "/charset.pivot" | | 67 | #define CS_PIVOT _PATH_CSMAPPER "/charset.pivot" |
68 | | | 68 | |
69 | | | 69 | |
70 | /* ---------------------------------------------------------------------- */ | | 70 | /* ---------------------------------------------------------------------- */ |
71 | | | 71 | |
72 | static int | | 72 | static int |
73 | get32(struct _region *r, uint32_t *rval) | | 73 | get32(struct _region *r, uint32_t *rval) |
74 | { | | 74 | { |
75 | if (_region_size(r) != 4) | | 75 | if (_region_size(r) != 4) |
76 | return EFTYPE; | | 76 | return EFTYPE; |
77 | | | 77 | |
78 | memcpy(rval, _region_head(r), (size_t)4); | | 78 | memcpy(rval, _region_head(r), (size_t)4); |
79 | *rval = be32toh(*rval); | | 79 | *rval = be32toh(*rval); |
80 | | | 80 | |
81 | return 0; | | 81 | return 0; |
82 | } | | 82 | } |
83 | | | 83 | |
84 | static int | | 84 | static int |
85 | open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src) | | 85 | open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src) |
86 | { | | 86 | { |
87 | int ret; | | 87 | int ret; |
88 | struct _region r; | | 88 | struct _region r; |
89 | | | 89 | |
90 | ret = _db_lookup_by_s(db, src, &r, NULL); | | 90 | ret = _db_lookup_by_s(db, src, &r, NULL); |
91 | if (ret) | | 91 | if (ret) |
92 | return ret; | | 92 | return ret; |
93 | ret = _db_open(subdb, &r, _CITRUS_PIVOT_SUB_MAGIC, _db_hash_std, NULL); | | 93 | ret = _db_open(subdb, &r, _CITRUS_PIVOT_SUB_MAGIC, _db_hash_std, NULL); |
94 | if (ret) | | 94 | if (ret) |
95 | return ret; | | 95 | return ret; |
96 | | | 96 | |
97 | return 0; | | 97 | return 0; |
98 | } | | 98 | } |
99 | | | 99 | |
100 | | | 100 | |
101 | #define NO_SUCH_FILE EOPNOTSUPP | | 101 | #define NO_SUCH_FILE EOPNOTSUPP |
102 | static int | | 102 | static int |
103 | find_best_pivot_pvdb(const char *src, const char *dst, char *pivot, | | 103 | find_best_pivot_pvdb(const char *src, const char *dst, char *pivot, |
104 | size_t pvlen, unsigned long *rnorm) | | 104 | size_t pvlen, unsigned long *rnorm) |
105 | { | | 105 | { |
106 | int ret, num, i; | | 106 | int ret, num, i; |
107 | struct _region fr, r1, r2; | | 107 | struct _region fr, r1, r2; |
108 | struct _citrus_db *db1, *db2, *db3; | | 108 | struct _citrus_db *db1, *db2, *db3; |
109 | char buf[LINE_MAX]; | | 109 | char buf[LINE_MAX]; |
110 | unsigned long norm; | | 110 | unsigned long norm; |
111 | uint32_t val32; | | 111 | uint32_t val32; |
112 | | | 112 | |
113 | ret = _map_file(&fr, CS_PIVOT ".pvdb"); | | 113 | ret = _map_file(&fr, CS_PIVOT ".pvdb"); |
114 | if (ret) { | | 114 | if (ret) { |
115 | if (ret == ENOENT) | | 115 | if (ret == ENOENT) |
116 | ret = NO_SUCH_FILE; | | 116 | ret = NO_SUCH_FILE; |
117 | return ret; | | 117 | return ret; |
118 | } | | 118 | } |
119 | ret = _db_open(&db1, &fr, _CITRUS_PIVOT_MAGIC, _db_hash_std, NULL); | | 119 | ret = _db_open(&db1, &fr, _CITRUS_PIVOT_MAGIC, _db_hash_std, NULL); |
120 | if (ret) | | 120 | if (ret) |
121 | goto quit1; | | 121 | goto quit1; |
122 | ret = open_subdb(&db2, db1, src); | | 122 | ret = open_subdb(&db2, db1, src); |
123 | if (ret) | | 123 | if (ret) |
124 | goto quit2; | | 124 | goto quit2; |
125 | | | 125 | |
126 | num = _db_get_num_entries(db2); | | 126 | num = _db_get_num_entries(db2); |
127 | *rnorm = ULONG_MAX; | | 127 | *rnorm = ULONG_MAX; |
128 | for (i = 0; i < num; i++) { | | 128 | for (i = 0; i < num; i++) { |
129 | /* iterate each pivot */ | | 129 | /* iterate each pivot */ |
130 | ret = _db_get_entry(db2, i, &r1, &r2); | | 130 | ret = _db_get_entry(db2, i, &r1, &r2); |
131 | if (ret) | | 131 | if (ret) |
132 | goto quit3; | | 132 | goto quit3; |
133 | /* r1:pivot name, r2:norm among src and pivot */ | | 133 | /* r1:pivot name, r2:norm among src and pivot */ |
134 | ret = get32(&r2, &val32); | | 134 | ret = get32(&r2, &val32); |
135 | if (ret) | | 135 | if (ret) |
136 | goto quit3; | | 136 | goto quit3; |
137 | norm = val32; | | 137 | norm = val32; |
138 | snprintf(buf, sizeof(buf), "%.*s", | | 138 | snprintf(buf, sizeof(buf), "%.*s", |
139 | (int)_region_size(&r1), (char *)_region_head(&r1)); | | 139 | (int)_region_size(&r1), (char *)_region_head(&r1)); |
140 | /* buf: pivot name */ | | 140 | /* buf: pivot name */ |
141 | ret = open_subdb(&db3, db1, buf); | | 141 | ret = open_subdb(&db3, db1, buf); |
142 | if (ret) | | 142 | if (ret) |
143 | goto quit3; | | 143 | goto quit3; |
144 | if (_db_lookup_by_s(db3, dst, &r2, NULL) != 0) | | 144 | if (_db_lookup_by_s(db3, dst, &r2, NULL) != 0) |
145 | /* don't break the loop, test all src/dst pairs. */ | | 145 | /* don't break the loop, test all src/dst pairs. */ |
146 | goto quit4; | | 146 | goto quit4; |
147 | /* r2: norm among pivot and dst */ | | 147 | /* r2: norm among pivot and dst */ |
148 | ret = get32(&r2, &val32); | | 148 | ret = get32(&r2, &val32); |
149 | if (ret) | | 149 | if (ret) |
150 | goto quit4; | | 150 | goto quit4; |
151 | norm += val32; | | 151 | norm += val32; |
152 | /* judge minimum norm */ | | 152 | /* judge minimum norm */ |
153 | if (norm < *rnorm) { | | 153 | if (norm < *rnorm) { |
154 | *rnorm = norm; | | 154 | *rnorm = norm; |
155 | strlcpy(pivot, buf, pvlen); | | 155 | strlcpy(pivot, buf, pvlen); |
156 | } | | 156 | } |
157 | quit4: | | 157 | quit4: |
158 | _db_close(db3); | | 158 | _db_close(db3); |
159 | if (ret) | | 159 | if (ret) |
160 | goto quit3; | | 160 | goto quit3; |
161 | } | | 161 | } |
162 | quit3: | | 162 | quit3: |
163 | _db_close(db2); | | 163 | _db_close(db2); |
164 | quit2: | | 164 | quit2: |
165 | _db_close(db1); | | 165 | _db_close(db1); |
166 | quit1: | | 166 | quit1: |
167 | _unmap_file(&fr); | | 167 | _unmap_file(&fr); |
168 | if (ret) | | 168 | if (ret) |
169 | return ret; | | 169 | return ret; |
170 | | | 170 | |
171 | if (*rnorm == ULONG_MAX) | | 171 | if (*rnorm == ULONG_MAX) |
172 | return ENOENT; | | 172 | return ENOENT; |
173 | | | 173 | |
174 | return 0; | | 174 | return 0; |
175 | } | | 175 | } |
176 | | | 176 | |
177 | /* ---------------------------------------------------------------------- */ | | 177 | /* ---------------------------------------------------------------------- */ |
178 | | | 178 | |
179 | struct zone { | | 179 | struct zone { |
180 | const char *begin, *end; | | 180 | const char *begin, *end; |
181 | }; | | 181 | }; |
182 | | | 182 | |
183 | struct parse_arg { | | 183 | struct parse_arg { |
184 | char dst[PATH_MAX]; | | 184 | char dst[PATH_MAX]; |
185 | unsigned long norm; | | 185 | unsigned long norm; |
186 | }; | | 186 | }; |
187 | | | 187 | |
188 | static int | | 188 | static int |
189 | parse_line(struct parse_arg *pa, struct _region *r) | | 189 | parse_line(struct parse_arg *pa, struct _region *r) |
190 | { | | 190 | { |
191 | char buf[20]; | | 191 | char buf[20]; |
192 | struct zone z1, z2; | | 192 | struct zone z1, z2; |
193 | size_t len; | | 193 | size_t len; |
194 | | | 194 | |
195 | len = _region_size(r); | | 195 | len = _region_size(r); |
196 | z1.begin = _bcs_skip_ws_len(_region_head(r), &len); | | 196 | z1.begin = _bcs_skip_ws_len(_region_head(r), &len); |
197 | if (len == 0) | | 197 | if (len == 0) |
198 | return EFTYPE; | | 198 | return EFTYPE; |
199 | z1.end = _bcs_skip_nonws_len(z1.begin, &len); | | 199 | z1.end = _bcs_skip_nonws_len(z1.begin, &len); |
200 | if (len == 0) | | 200 | if (len == 0) |
201 | return EFTYPE; | | 201 | return EFTYPE; |
202 | z2.begin = _bcs_skip_ws_len(z1.end, &len); | | 202 | z2.begin = _bcs_skip_ws_len(z1.end, &len); |
203 | if (len == 0) | | 203 | if (len == 0) |
204 | return EFTYPE; | | 204 | return EFTYPE; |
205 | z2.end = _bcs_skip_nonws_len(z2.begin, &len); | | 205 | z2.end = _bcs_skip_nonws_len(z2.begin, &len); |
206 | | | 206 | |
207 | /* z1 : dst name, z2 : norm */ | | 207 | /* z1 : dst name, z2 : norm */ |
208 | snprintf(pa->dst, sizeof(pa->dst), | | 208 | snprintf(pa->dst, sizeof(pa->dst), |
209 | "%.*s", (int)(z1.end-z1.begin), z1.begin); | | 209 | "%.*s", (int)(z1.end-z1.begin), z1.begin); |
210 | snprintf(buf, sizeof(buf), | | 210 | snprintf(buf, sizeof(buf), |
211 | "%.*s", (int)(z2.end-z2.begin), z2.begin); | | 211 | "%.*s", (int)(z2.end-z2.begin), z2.begin); |
212 | pa->norm = _bcs_strtoul(buf, NULL, 0); | | 212 | pa->norm = _bcs_strtoul(buf, NULL, 0); |
213 | | | 213 | |
214 | return 0; | | 214 | return 0; |
215 | } | | 215 | } |
216 | | | 216 | |
217 | static int | | 217 | static int |
218 | find_dst(struct parse_arg *pasrc, const char *dst) | | 218 | find_dst(struct parse_arg *pasrc, const char *dst) |
219 | { | | 219 | { |
220 | int ret; | | 220 | int ret; |
221 | struct parse_arg padst; | | 221 | struct parse_arg padst; |
222 | struct _lookup *cl; | | 222 | struct _lookup *cl; |
223 | struct _region data; | | 223 | struct _region data; |
224 | | | 224 | |
225 | ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE); | | 225 | ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE); |
226 | if (ret) | | 226 | if (ret) |
227 | return ret; | | 227 | return ret; |
228 | | | 228 | |
229 | ret = _lookup_seq_lookup(cl, pasrc->dst, &data); | | 229 | ret = _lookup_seq_lookup(cl, pasrc->dst, &data); |
230 | while (ret == 0) { | | 230 | while (ret == 0) { |
231 | ret = parse_line(&padst, &data); | | 231 | ret = parse_line(&padst, &data); |
232 | if (ret) | | 232 | if (ret) |
233 | break; | | 233 | break; |
234 | if (strcmp(dst, padst.dst) == 0) { | | 234 | if (strcmp(dst, padst.dst) == 0) { |
235 | pasrc->norm += padst.norm; | | 235 | pasrc->norm += padst.norm; |
236 | break; | | 236 | break; |
237 | } | | 237 | } |
238 | ret = _lookup_seq_next(cl, NULL, &data); | | 238 | ret = _lookup_seq_next(cl, NULL, &data); |
239 | } | | 239 | } |
240 | _lookup_seq_close(cl); | | 240 | _lookup_seq_close(cl); |
241 | | | 241 | |
242 | return ret; | | 242 | return ret; |
243 | } | | 243 | } |
244 | | | 244 | |
245 | static int | | 245 | static int |
246 | find_best_pivot_lookup(const char *src, const char *dst, char *pivot, | | 246 | find_best_pivot_lookup(const char *src, const char *dst, char *pivot, |
247 | size_t pvlen, unsigned long *rnorm) | | 247 | size_t pvlen, unsigned long *rnorm) |
248 | { | | 248 | { |
249 | int ret; | | 249 | int ret; |
250 | struct _lookup *cl; | | 250 | struct _lookup *cl; |
251 | struct _region data; | | 251 | struct _region data; |
252 | struct parse_arg pa; | | 252 | struct parse_arg pa; |
253 | unsigned long norm_min; | | 253 | unsigned long norm_min; |
254 | char pivot_min[PATH_MAX]; | | 254 | char pivot_min[PATH_MAX]; |
255 | | | 255 | |
256 | ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE); | | 256 | ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE); |
257 | if (ret) | | 257 | if (ret) |
258 | return ret; | | 258 | return ret; |
259 | | | 259 | |
260 | norm_min = ULONG_MAX; | | 260 | norm_min = ULONG_MAX; |
261 | | | 261 | |
262 | /* find pivot code */ | | 262 | /* find pivot code */ |
263 | ret = _lookup_seq_lookup(cl, src, &data); | | 263 | ret = _lookup_seq_lookup(cl, src, &data); |
264 | while (ret == 0) { | | 264 | while (ret == 0) { |
265 | ret = parse_line(&pa, &data); | | 265 | ret = parse_line(&pa, &data); |
266 | if (ret) | | 266 | if (ret) |
267 | break; | | 267 | break; |
268 | ret = find_dst(&pa, dst); | | 268 | ret = find_dst(&pa, dst); |
269 | if (ret) | | 269 | if (ret) |
270 | break; | | 270 | break; |
271 | if (pa.norm < norm_min) { | | 271 | if (pa.norm < norm_min) { |
272 | norm_min = pa.norm; | | 272 | norm_min = pa.norm; |
273 | strlcpy(pivot_min, pa.dst, sizeof(pivot_min)); | | 273 | strlcpy(pivot_min, pa.dst, sizeof(pivot_min)); |
274 | } | | 274 | } |
275 | ret = _lookup_seq_next(cl, NULL, &data); | | 275 | ret = _lookup_seq_next(cl, NULL, &data); |
276 | } | | 276 | } |
277 | _lookup_seq_close(cl); | | 277 | _lookup_seq_close(cl); |
278 | | | 278 | |
279 | if (ret != ENOENT) | | 279 | if (ret != ENOENT) |
280 | return ret; | | 280 | return ret; |
281 | if (norm_min == ULONG_MAX) | | 281 | if (norm_min == ULONG_MAX) |
282 | return ENOENT; | | 282 | return ENOENT; |
283 | strlcpy(pivot, pivot_min, pvlen); | | 283 | strlcpy(pivot, pivot_min, pvlen); |
284 | if (rnorm) | | 284 | if (rnorm) |
285 | *rnorm = norm_min; | | 285 | *rnorm = norm_min; |
286 | | | 286 | |
287 | return 0; | | 287 | return 0; |
288 | } | | 288 | } |
289 | | | 289 | |
290 | static int | | 290 | static int |
291 | find_best_pivot(const char *src, const char *dst, char *pivot, size_t pvlen, | | 291 | find_best_pivot(const char *src, const char *dst, char *pivot, size_t pvlen, |
292 | unsigned long *rnorm) | | 292 | unsigned long *rnorm) |
293 | { | | 293 | { |
294 | int ret; | | 294 | int ret; |
295 | | | 295 | |
296 | ret = find_best_pivot_pvdb(src, dst, pivot, pvlen, rnorm); | | 296 | ret = find_best_pivot_pvdb(src, dst, pivot, pvlen, rnorm); |
297 | if (ret == NO_SUCH_FILE) | | 297 | if (ret == NO_SUCH_FILE) |
298 | ret = find_best_pivot_lookup(src, dst, pivot, pvlen, rnorm); | | 298 | ret = find_best_pivot_lookup(src, dst, pivot, pvlen, rnorm); |
299 | | | 299 | |
300 | return ret; | | 300 | return ret; |
301 | } | | 301 | } |
302 | | | 302 | |
303 | static __inline int | | 303 | static __inline int |
304 | open_serial_mapper(struct _citrus_mapper_area *__restrict ma, | | 304 | open_serial_mapper(struct _citrus_mapper_area *__restrict ma, |
305 | struct _citrus_mapper * __restrict * __restrict rcm, | | 305 | struct _citrus_mapper * __restrict * __restrict rcm, |
306 | const char *src, const char *pivot, const char *dst) | | 306 | const char *src, const char *pivot, const char *dst) |
307 | { | | 307 | { |
308 | char buf[PATH_MAX]; | | 308 | char buf[4 * PATH_MAX]; |
309 | | | 309 | |
310 | snprintf(buf, sizeof(buf), "%s/%s,%s/%s", src, pivot, pivot, dst); | | 310 | snprintf(buf, sizeof(buf), "%s/%s,%s/%s", src, pivot, pivot, dst); |
311 | | | 311 | |
312 | return _mapper_open_direct(ma, rcm, "mapper_serial", buf); | | 312 | return _mapper_open_direct(ma, rcm, "mapper_serial", buf); |
313 | } | | 313 | } |
314 | | | 314 | |
315 | static struct _citrus_csmapper *csm_none = NULL; | | 315 | static struct _citrus_csmapper *csm_none = NULL; |
316 | static int | | 316 | static int |
317 | get_none(struct _citrus_mapper_area *__restrict ma, | | 317 | get_none(struct _citrus_mapper_area *__restrict ma, |
318 | struct _citrus_csmapper *__restrict *__restrict rcsm) | | 318 | struct _citrus_csmapper *__restrict *__restrict rcsm) |
319 | { | | 319 | { |
320 | int ret; | | 320 | int ret; |
321 | | | 321 | |
322 | rwlock_wrlock(&lock); | | 322 | rwlock_wrlock(&lock); |
323 | if (csm_none) { | | 323 | if (csm_none) { |
324 | *rcsm = csm_none; | | 324 | *rcsm = csm_none; |
325 | ret = 0; | | 325 | ret = 0; |
326 | goto quit; | | 326 | goto quit; |
327 | } | | 327 | } |
328 | | | 328 | |
329 | ret = _mapper_open_direct(ma, &csm_none, "mapper_none", ""); | | 329 | ret = _mapper_open_direct(ma, &csm_none, "mapper_none", ""); |
330 | if (ret) | | 330 | if (ret) |
331 | goto quit; | | 331 | goto quit; |
332 | _mapper_set_persistent(csm_none); | | 332 | _mapper_set_persistent(csm_none); |
333 | | | 333 | |
334 | *rcsm = csm_none; | | 334 | *rcsm = csm_none; |
335 | ret = 0; | | 335 | ret = 0; |
336 | quit: | | 336 | quit: |
337 | rwlock_unlock(&lock); | | 337 | rwlock_unlock(&lock); |
338 | return ret; | | 338 | return ret; |
339 | } | | 339 | } |
340 | | | 340 | |
341 | int | | 341 | int |
342 | _citrus_csmapper_open(struct _citrus_csmapper * __restrict * __restrict rcsm, | | 342 | _citrus_csmapper_open(struct _citrus_csmapper * __restrict * __restrict rcsm, |
343 | const char * __restrict src, const char * __restrict dst, | | 343 | const char * __restrict src, const char * __restrict dst, |
344 | uint32_t flags, unsigned long *rnorm) | | 344 | uint32_t flags, unsigned long *rnorm) |
345 | { | | 345 | { |
346 | int ret; | | 346 | int ret; |
347 | char buf1[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX]; | | 347 | char buf1[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX]; |
348 | const char *realsrc, *realdst; | | 348 | const char *realsrc, *realdst; |
349 | unsigned long norm; | | 349 | unsigned long norm; |
350 | | | 350 | |
351 | norm = 0; /* XXX gcc */ | | 351 | norm = 0; /* XXX gcc */ |
352 | | | 352 | |
353 | ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER); | | 353 | ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER); |
354 | if (ret) | | 354 | if (ret) |
355 | return ret; | | 355 | return ret; |
356 | | | 356 | |
357 | realsrc = _lookup_alias(CS_ALIAS, src, buf1, sizeof(buf1), | | 357 | realsrc = _lookup_alias(CS_ALIAS, src, buf1, sizeof(buf1), |
358 | _LOOKUP_CASE_IGNORE); | | 358 | _LOOKUP_CASE_IGNORE); |
359 | realdst = _lookup_alias(CS_ALIAS, dst, buf2, sizeof(buf2), | | 359 | realdst = _lookup_alias(CS_ALIAS, dst, buf2, sizeof(buf2), |
360 | _LOOKUP_CASE_IGNORE); | | 360 | _LOOKUP_CASE_IGNORE); |
361 | if (!strcmp(realsrc, realdst)) { | | 361 | if (!strcmp(realsrc, realdst)) { |
362 | ret = get_none(maparea, rcsm); | | 362 | ret = get_none(maparea, rcsm); |
363 | if (ret == 0 && rnorm != NULL) | | 363 | if (ret == 0 && rnorm != NULL) |
364 | *rnorm = 0; | | 364 | *rnorm = 0; |
365 | return ret; | | 365 | return ret; |
366 | } | | 366 | } |
367 | | | 367 | |
368 | snprintf(key, sizeof(key), "%s/%s", realsrc, realdst); | | 368 | snprintf(key, sizeof(key), "%s/%s", realsrc, realdst); |
369 | | | 369 | |
370 | ret = _mapper_open(maparea, rcsm, key); | | 370 | ret = _mapper_open(maparea, rcsm, key); |
371 | if (ret == 0) { | | 371 | if (ret == 0) { |
372 | if (rnorm != NULL) | | 372 | if (rnorm != NULL) |
373 | *rnorm = 0; | | 373 | *rnorm = 0; |
374 | return 0; | | 374 | return 0; |
375 | } | | 375 | } |
376 | if (ret != ENOENT || (flags & _CSMAPPER_F_PREVENT_PIVOT)!=0) | | 376 | if (ret != ENOENT || (flags & _CSMAPPER_F_PREVENT_PIVOT)!=0) |
377 | return ret; | | 377 | return ret; |
378 | | | 378 | |
379 | ret = find_best_pivot(realsrc, realdst, pivot, sizeof(pivot), &norm); | | 379 | ret = find_best_pivot(realsrc, realdst, pivot, sizeof(pivot), &norm); |
380 | if (ret) | | 380 | if (ret) |
381 | return ret; | | 381 | return ret; |
382 | | | 382 | |
383 | ret = open_serial_mapper(maparea, rcsm, realsrc, pivot, realdst); | | 383 | ret = open_serial_mapper(maparea, rcsm, realsrc, pivot, realdst); |
384 | if (ret == 0 && rnorm != NULL) | | 384 | if (ret == 0 && rnorm != NULL) |
385 | *rnorm = norm; | | 385 | *rnorm = norm; |
386 | | | 386 | |
387 | return ret; | | 387 | return ret; |
388 | } | | 388 | } |