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