xref: /netbsd-src/lib/libc/iconv/iconv.c (revision 77a1ad5f0039ea2bc6af76846debc20728bae498)
1*77a1ad5fSkamil /*	$NetBSD: iconv.c,v 1.14 2019/10/24 18:17:59 kamil Exp $	*/
2ff5c3e68Stshiozak 
3ff5c3e68Stshiozak /*-
4ff5c3e68Stshiozak  * Copyright (c)2003 Citrus Project,
5ff5c3e68Stshiozak  * All rights reserved.
6ff5c3e68Stshiozak  *
7ff5c3e68Stshiozak  * Redistribution and use in source and binary forms, with or without
8ff5c3e68Stshiozak  * modification, are permitted provided that the following conditions
9ff5c3e68Stshiozak  * are met:
10ff5c3e68Stshiozak  * 1. Redistributions of source code must retain the above copyright
11ff5c3e68Stshiozak  *    notice, this list of conditions and the following disclaimer.
12ff5c3e68Stshiozak  * 2. Redistributions in binary form must reproduce the above copyright
13ff5c3e68Stshiozak  *    notice, this list of conditions and the following disclaimer in the
14ff5c3e68Stshiozak  *    documentation and/or other materials provided with the distribution.
15ff5c3e68Stshiozak  *
16ff5c3e68Stshiozak  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17ff5c3e68Stshiozak  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18ff5c3e68Stshiozak  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19ff5c3e68Stshiozak  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20ff5c3e68Stshiozak  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21ff5c3e68Stshiozak  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22ff5c3e68Stshiozak  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23ff5c3e68Stshiozak  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24ff5c3e68Stshiozak  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25ff5c3e68Stshiozak  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26ff5c3e68Stshiozak  * SUCH DAMAGE.
27ff5c3e68Stshiozak  */
28ff5c3e68Stshiozak 
29ff5c3e68Stshiozak #include <sys/cdefs.h>
30ff5c3e68Stshiozak #if defined(LIBC_SCCS) && !defined(lint)
31*77a1ad5fSkamil __RCSID("$NetBSD: iconv.c,v 1.14 2019/10/24 18:17:59 kamil Exp $");
32ff5c3e68Stshiozak #endif /* LIBC_SCCS and not lint */
33ff5c3e68Stshiozak 
34ff5c3e68Stshiozak #include "namespace.h"
35ff5c3e68Stshiozak #include <assert.h>
36ff5c3e68Stshiozak #include <errno.h>
37ff5c3e68Stshiozak #include <paths.h>
3858db2e99Stshiozak #include <sys/queue.h>
39ff5c3e68Stshiozak 
40ff5c3e68Stshiozak #include <iconv.h>
41ff5c3e68Stshiozak 
4296b41760Schristos #ifdef __weak_alias
__weak_alias(iconv,_iconv)4396b41760Schristos __weak_alias(iconv, _iconv)
4496b41760Schristos __weak_alias(iconv_open, _iconv_open)
4596b41760Schristos __weak_alias(iconv_close, _iconv_close)
4696b41760Schristos #endif
4796b41760Schristos 
48ff5c3e68Stshiozak #include <sys/types.h>
4952ed7b03Stnozaki #include "citrus_types.h"
5052ed7b03Stnozaki #include "citrus_module.h"
5152ed7b03Stnozaki #include "citrus_esdb.h"
5252ed7b03Stnozaki #include "citrus_hash.h"
5352ed7b03Stnozaki #include "citrus_iconv.h"
54ff5c3e68Stshiozak 
55ff5c3e68Stshiozak #define ISBADF(_h_)	(!(_h_) || (_h_) == (iconv_t)-1)
56ff5c3e68Stshiozak 
57466a3e5dSjoerg 
58ff5c3e68Stshiozak iconv_t
5996b41760Schristos iconv_open(const char *out, const char *in)
60ff5c3e68Stshiozak {
61ff5c3e68Stshiozak 	int ret;
62ff5c3e68Stshiozak 	struct _citrus_iconv *handle;
63ff5c3e68Stshiozak 
64466a3e5dSjoerg 	ret = _citrus_iconv_open(&handle, _PATH_ICONV, in, out);
65ff5c3e68Stshiozak 	if (ret) {
667204e681Stshiozak 		errno = ret == ENOENT? EINVAL : ret;
67ff5c3e68Stshiozak 		return ((iconv_t)-1);
68ff5c3e68Stshiozak 	}
69ff5c3e68Stshiozak 
7058db2e99Stshiozak 	return ((iconv_t)(void *)handle);
71ff5c3e68Stshiozak }
72ff5c3e68Stshiozak 
73ff5c3e68Stshiozak int
iconv_close(iconv_t handle)7496b41760Schristos iconv_close(iconv_t handle)
75ff5c3e68Stshiozak {
76ff5c3e68Stshiozak 	if (ISBADF(handle)) {
77ff5c3e68Stshiozak 		errno = EBADF;
78ff5c3e68Stshiozak 		return (-1);
79ff5c3e68Stshiozak 	}
80ff5c3e68Stshiozak 
8158db2e99Stshiozak 	_citrus_iconv_close((struct _citrus_iconv *)(void *)handle);
82ff5c3e68Stshiozak 
83ff5c3e68Stshiozak 	return (0);
84ff5c3e68Stshiozak }
85ff5c3e68Stshiozak 
86ff5c3e68Stshiozak size_t
iconv(iconv_t handle,char ** in,size_t * szin,char ** out,size_t * szout)87*77a1ad5fSkamil iconv(iconv_t handle, char **in, size_t *szin, char **out, size_t *szout)
88ff5c3e68Stshiozak {
89ff5c3e68Stshiozak 	int err;
90ff5c3e68Stshiozak 	size_t ret;
91ff5c3e68Stshiozak 
92ff5c3e68Stshiozak 	if (ISBADF(handle)) {
93ff5c3e68Stshiozak 		errno = EBADF;
94ff5c3e68Stshiozak 		return ((size_t)-1);
95ff5c3e68Stshiozak 	}
96ff5c3e68Stshiozak 
97ff5c3e68Stshiozak 	err = _citrus_iconv_convert(
98*77a1ad5fSkamil 		(struct _citrus_iconv *)(void *)handle,
99*77a1ad5fSkamil 		(const char **)(void *)in, szin, out, szout, 0, &ret);
100ff5c3e68Stshiozak 	if (err) {
101ff5c3e68Stshiozak 		errno = err;
102ff5c3e68Stshiozak 		ret = (size_t)-1;
103ff5c3e68Stshiozak 	}
104ff5c3e68Stshiozak 
105ff5c3e68Stshiozak 	return (ret);
106ff5c3e68Stshiozak }
107ff5c3e68Stshiozak 
108ff5c3e68Stshiozak size_t
__iconv(iconv_t handle,char ** in,size_t * szin,char ** out,size_t * szout,u_int32_t flags,size_t * invalids)109*77a1ad5fSkamil __iconv(iconv_t handle, char **in, size_t *szin, char **out,
110ff5c3e68Stshiozak 	size_t *szout, u_int32_t flags, size_t *invalids)
111ff5c3e68Stshiozak {
112ff5c3e68Stshiozak 	int err;
113ff5c3e68Stshiozak 	size_t ret;
114ff5c3e68Stshiozak 
115ff5c3e68Stshiozak 	if (ISBADF(handle)) {
116ff5c3e68Stshiozak 		errno = EBADF;
117ff5c3e68Stshiozak 		return ((size_t)-1);
118ff5c3e68Stshiozak 	}
119ff5c3e68Stshiozak 
120ff5c3e68Stshiozak 	err = _citrus_iconv_convert(
121*77a1ad5fSkamil 		(struct _citrus_iconv *)(void *)handle,
122*77a1ad5fSkamil 		(const char **)(void *)in, szin, out, szout, flags, &ret);
123ff5c3e68Stshiozak 	if (invalids)
124ff5c3e68Stshiozak 		*invalids = ret;
125ff5c3e68Stshiozak 	if (err) {
126ff5c3e68Stshiozak 		errno = err;
127ff5c3e68Stshiozak 		ret = (size_t)-1;
128ff5c3e68Stshiozak 	}
129ff5c3e68Stshiozak 
130ff5c3e68Stshiozak 	return (ret);
131ff5c3e68Stshiozak }
132ff5c3e68Stshiozak 
133ff5c3e68Stshiozak int
__iconv_get_list(char *** rlist,size_t * rsz)134ff5c3e68Stshiozak __iconv_get_list(char ***rlist, size_t *rsz)
135ff5c3e68Stshiozak {
136ff5c3e68Stshiozak 	int ret;
137ff5c3e68Stshiozak 
138ff5c3e68Stshiozak 	ret = _citrus_esdb_get_list(rlist, rsz);
139ff5c3e68Stshiozak 	if (ret) {
140ff5c3e68Stshiozak 		errno = ret;
141ff5c3e68Stshiozak 		return -1;
142ff5c3e68Stshiozak 	}
143ff5c3e68Stshiozak 
144ff5c3e68Stshiozak 	return 0;
145ff5c3e68Stshiozak }
146ff5c3e68Stshiozak 
147ff5c3e68Stshiozak void
__iconv_free_list(char ** list,size_t sz)148ff5c3e68Stshiozak __iconv_free_list(char **list, size_t sz)
149ff5c3e68Stshiozak {
150ff5c3e68Stshiozak 	_citrus_esdb_free_list(list, sz);
151ff5c3e68Stshiozak }
152