]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libc/iconv/bsd_iconv.c
Import device-tree files from Linux 6.0
[FreeBSD/FreeBSD.git] / lib / libc / iconv / bsd_iconv.c
1 /* $FreeBSD$ */
2 /* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */
3
4 /*-
5  * SPDX-License-Identifier: BSD-2-Clause
6  *
7  * Copyright (c) 2003 Citrus Project,
8  * Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include <sys/cdefs.h>
34 #include <sys/queue.h>
35 #include <sys/types.h>
36
37 #include <assert.h>
38 #include <errno.h>
39 #include <iconv.h>
40 #include <limits.h>
41 #include <paths.h>
42 #include <stdbool.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include "citrus_types.h"
47 #include "citrus_module.h"
48 #include "citrus_esdb.h"
49 #include "citrus_hash.h"
50 #include "citrus_iconv.h"
51
52 #include "iconv-internal.h"
53
54 #define ISBADF(_h_)     (!(_h_) || (_h_) == (iconv_t)-1)
55
56 static iconv_t
57 __bsd___iconv_open(const char *out, const char *in, struct _citrus_iconv *handle)
58 {
59         int ret;
60
61         /*
62          * Remove anything following a //, as these are options (like
63          * //ignore, //translate, etc) and we just don't handle them.
64          * This is for compatibility with software that uses these
65          * blindly.
66          */
67         ret = _citrus_iconv_open(&handle, in, out);
68         if (ret) {
69                 errno = ret == ENOENT ? EINVAL : ret;
70                 return ((iconv_t)-1);
71         }
72
73         handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE");
74         handle->cv_shared->ci_ilseq_invalid = false;
75         handle->cv_shared->ci_hooks = NULL;
76
77         return ((iconv_t)(void *)handle);
78 }
79
80 iconv_t
81 __bsd_iconv_open(const char *out, const char *in)
82 {
83
84         return (__bsd___iconv_open(out, in, NULL));
85 }
86
87 int
88 __bsd_iconv_open_into(const char *out, const char *in, iconv_allocation_t *ptr)
89 {
90         struct _citrus_iconv *handle;
91
92         handle = (struct _citrus_iconv *)ptr;
93         return ((__bsd___iconv_open(out, in, handle) == (iconv_t)-1) ? -1 : 0);
94 }
95
96 int
97 __bsd_iconv_close(iconv_t handle)
98 {
99
100         if (ISBADF(handle)) {
101                 errno = EBADF;
102                 return (-1);
103         }
104
105         _citrus_iconv_close((struct _citrus_iconv *)(void *)handle);
106
107         return (0);
108 }
109
110 size_t
111 __bsd_iconv(iconv_t handle, char **in, size_t *szin, char **out, size_t *szout)
112 {
113         size_t ret;
114         int err;
115
116         if (ISBADF(handle)) {
117                 errno = EBADF;
118                 return ((size_t)-1);
119         }
120
121         err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
122             in, szin, out, szout, 0, &ret);
123         if (err) {
124                 errno = err;
125                 ret = (size_t)-1;
126         }
127
128         return (ret);
129 }
130
131 size_t
132 __bsd___iconv(iconv_t handle, char **in, size_t *szin, char **out,
133     size_t *szout, uint32_t flags, size_t *invalids)
134 {
135         size_t ret;
136         int err;
137
138         if (ISBADF(handle)) {
139                 errno = EBADF;
140                 return ((size_t)-1);
141         }
142
143         err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
144             in, szin, out, szout, flags, &ret);
145         if (invalids)
146                 *invalids = ret;
147         if (err) {
148                 errno = err;
149                 ret = (size_t)-1;
150         }
151
152         return (ret);
153 }
154
155 int
156 __bsd___iconv_get_list(char ***rlist, size_t *rsz, bool sorted)
157 {
158         int ret;
159
160         ret = _citrus_esdb_get_list(rlist, rsz, sorted);
161         if (ret) {
162                 errno = ret;
163                 return (-1);
164         }
165
166         return (0);
167 }
168
169 void
170 __bsd___iconv_free_list(char **list, size_t sz)
171 {
172
173         _citrus_esdb_free_list(list, sz);
174 }
175
176 /*
177  * GNU-compatibile non-standard interfaces.
178  */
179 static int
180 qsort_helper(const void *first, const void *second)
181 {
182         const char * const *s1;
183         const char * const *s2;
184
185         s1 = first;
186         s2 = second;
187         return (strcmp(*s1, *s2));
188 }
189
190 void
191 __bsd_iconvlist(int (*do_one) (unsigned int, const char * const *,
192     void *), void *data)
193 {
194         char **list, **names;
195         const char * const *np;
196         char *curitem, *curkey, *slashpos;
197         size_t sz;
198         unsigned int i, j, n;
199
200         i = 0;
201         names = NULL;
202
203         if (__bsd___iconv_get_list(&list, &sz, true)) {
204                 list = NULL;
205                 goto out;
206         }
207         qsort((void *)list, sz, sizeof(char *), qsort_helper);
208         while (i < sz) {
209                 j = 0;
210                 slashpos = strchr(list[i], '/');
211                 names = malloc(sz * sizeof(char *));
212                 if (names == NULL)
213                         goto out;
214                 curkey = strndup(list[i], slashpos - list[i]);
215                 if (curkey == NULL)
216                         goto out;
217                 names[j++] = curkey;
218                 for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) {
219                         slashpos = strchr(list[i], '/');
220                         if (strcmp(curkey, &slashpos[1]) == 0)
221                                 continue;
222                         curitem = strdup(&slashpos[1]);
223                         if (curitem == NULL)
224                                 goto out;
225                         names[j++] = curitem;
226                 }
227                 np = (const char * const *)names;
228                 do_one(j, np, data);
229                 for (n = 0; n < j; n++)
230                         free(names[n]);
231                 free(names);
232                 names = NULL;
233         }
234
235 out:
236         if (names != NULL) {
237                 for (n = 0; n < j; n++)
238                         free(names[n]);
239                 free(names);
240         }
241         if (list != NULL)
242                 __bsd___iconv_free_list(list, sz);
243 }
244
245 __inline const char *
246 __bsd_iconv_canonicalize(const char *name)
247 {
248
249         return (_citrus_iconv_canonicalize(name));
250 }
251
252 int
253 __bsd_iconvctl(iconv_t cd, int request, void *argument)
254 {
255         struct _citrus_iconv *cv;
256         struct iconv_hooks *hooks;
257         const char *convname;
258         char *dst;
259         int *i;
260         size_t srclen;
261
262         cv = (struct _citrus_iconv *)(void *)cd;
263         hooks = (struct iconv_hooks *)argument;
264         i = (int *)argument;
265
266         if (ISBADF(cd)) {
267                 errno = EBADF;
268                 return (-1);
269         }
270
271         switch (request) {
272         case ICONV_TRIVIALP:
273                 convname = cv->cv_shared->ci_convname;
274                 dst = strchr(convname, '/');
275                 srclen = dst - convname;
276                 dst++;
277                 *i = (srclen == strlen(dst)) && !memcmp(convname, dst, srclen);
278                 return (0);
279         case ICONV_GET_TRANSLITERATE:
280                 *i = 1;
281                 return (0);
282         case ICONV_SET_TRANSLITERATE:
283                 return  ((*i == 1) ? 0 : -1);
284         case ICONV_GET_DISCARD_ILSEQ:
285                 *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0;
286                 return (0);
287         case ICONV_SET_DISCARD_ILSEQ:
288                 cv->cv_shared->ci_discard_ilseq = *i;
289                 return (0);
290         case ICONV_SET_HOOKS:
291                 cv->cv_shared->ci_hooks = hooks;
292                 return (0);
293         case ICONV_SET_FALLBACKS:
294                 errno = EOPNOTSUPP;
295                 return (-1);
296         case ICONV_GET_ILSEQ_INVALID:
297                 *i = cv->cv_shared->ci_ilseq_invalid ? 1 : 0;
298                 return (0);
299         case ICONV_SET_ILSEQ_INVALID:
300                 cv->cv_shared->ci_ilseq_invalid = *i;
301                 return (0);
302         default:
303                 errno = EINVAL;
304                 return (-1);
305         }
306 }
307
308 void
309 __bsd_iconv_set_relocation_prefix(const char *orig_prefix __unused,
310     const char *curr_prefix __unused)
311 {
312
313 }