27 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/iconv.h>
34 #include <sys/malloc.h>
35 #include <sys/mount.h>
37 #include <sys/syslog.h>
39 #include "iconv_converter_if.h"
43 SYSCTL_NODE(_kern, OID_AUTO, iconv, CTLFLAG_RW, NULL,
"kernel iconv interface");
46 static MALLOC_DEFINE(M_ICONVDATA,
"iconv_data",
"ICONV data");
67 static TAILQ_HEAD(iconv_converter_list, iconv_converter_class)
68 iconv_converters = TAILQ_HEAD_INITIALIZER(iconv_converters);
74 iconv_cslist = TAILQ_HEAD_INITIALIZER(iconv_cslist);
75 static
int iconv_csid = 1;
77 static
char iconv_unicode_string[] = "unicode";
82 iconv_mod_unload(
void)
84 struct iconv_cspair *csp;
87 TAILQ_FOREACH(csp, &iconv_cslist, cp_link) {
88 if (csp->cp_refcount) {
94 while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL)
112 error = iconv_mod_unload();
129 kobj_class_compile((
struct kobj_class*)dcp);
131 TAILQ_INSERT_TAIL(&iconv_converters, dcp, cc_link);
139 ICDEBUG(
"converter have %d referenses left\n", dcp->refs);
142 TAILQ_REMOVE(&iconv_converters, dcp, cc_link);
143 kobj_class_free((
struct kobj_class*)dcp);
150 struct iconv_converter_class *dcp;
152 TAILQ_FOREACH(dcp, &iconv_converters, cc_link) {
155 if (
strcmp(name, ICONV_CONVERTER_NAME(dcp)) == 0) {
167 struct iconv_cspair *csp;
169 TAILQ_FOREACH(csp, &iconv_cslist, cp_link) {
182 struct iconv_converter_class *dcp,
void *data,
183 struct iconv_cspair **cspp)
185 struct iconv_cspair *csp;
187 int csize, ucsto, ucsfrom;
191 csize =
sizeof(*csp);
192 ucsto =
strcmp(to, iconv_unicode_string) == 0;
195 ucsfrom =
strcmp(from, iconv_unicode_string) == 0;
197 csize +=
strlen(from) + 1;
198 csp = malloc(csize, M_ICONV, M_WAITOK);
200 csp->cp_id = iconv_csid++;
202 cp = (
char*)(csp + 1);
208 csp->cp_to = iconv_unicode_string;
213 csp->cp_from = iconv_unicode_string;
216 TAILQ_INSERT_TAIL(&iconv_cslist, csp, cp_link);
224 TAILQ_REMOVE(&iconv_cslist, csp, cp_link);
226 free(csp->cp_data, M_ICONVDATA);
239 struct iconv_converter_class *dcp;
248 return ICONV_CONVERTER_OPEN(csp->cp_dcp, csp, NULL, handle);
254 TAILQ_FOREACH(dcp, &iconv_converters, cc_link) {
255 cnvname = ICONV_CONVERTER_NAME(dcp);
267 return ICONV_CONVERTER_OPEN(dcp, cspto, cspfrom, handle);
275 return ICONV_CONVERTER_CLOSE(handle);
282 return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 0, 0);
289 return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 0, casetype);
296 return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 1, 0);
303 return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 1, casetype);
309 return ICONV_CONVERTER_TOLOWER(handle, c);
315 return ICONV_CONVERTER_TOUPPER(handle, c);
325 struct iconv_converter_class *dcp;
332 TAILQ_FOREACH(dcp, &iconv_converters, cc_link) {
333 name = ICONV_CONVERTER_NAME(dcp);
336 error = SYSCTL_OUT(req, name,
strlen(name) + 1);
344 error = SYSCTL_OUT(req, &spc,
sizeof(spc));
348 SYSCTL_PROC(_kern_iconv, OID_AUTO, drvlist, CTLFLAG_RD | CTLTYPE_OPAQUE,
357 struct iconv_cspair *csp;
358 struct iconv_cspair_info csi;
362 bzero(&csi,
sizeof(csi));
363 csi.cs_version = ICONV_CSPAIR_INFO_VER;
365 TAILQ_FOREACH(csp, &iconv_cslist, cp_link) {
366 csi.cs_id = csp->cp_id;
367 csi.cs_refcount = csp->cp_refcount;
368 csi.cs_base = csp->cp_base ? csp->cp_base->cp_id : 0;
369 strcpy(csi.cs_to, csp->cp_to);
370 strcpy(csi.cs_from, csp->cp_from);
371 error = SYSCTL_OUT(req, &csi,
sizeof(csi));
379 SYSCTL_PROC(_kern_iconv, OID_AUTO, cslist, CTLFLAG_RD | CTLTYPE_OPAQUE,
383 iconv_add(
const char *converter,
const char *to,
const char *from)
385 struct iconv_converter_class *dcp;
386 struct iconv_cspair *csp;
400 struct iconv_converter_class *dcp;
401 struct iconv_cspair *csp;
402 struct iconv_add_in din;
403 struct iconv_add_out dout;
406 error = SYSCTL_IN(req, &din,
sizeof(din));
409 if (din.ia_version != ICONV_ADD_VER)
411 if (din.ia_datalen > ICONV_CSMAXDATALEN)
413 if (
strlen(din.ia_from) >= ICONV_CSNMAXLEN)
415 if (
strlen(din.ia_to) >= ICONV_CSNMAXLEN)
417 if (
strlen(din.ia_converter) >= ICONV_CNVNMAXLEN)
427 if (din.ia_datalen) {
428 csp->cp_data = malloc(din.ia_datalen, M_ICONVDATA, M_WAITOK);
429 error = copyin(din.ia_data, csp->cp_data, din.ia_datalen);
433 dout.ia_csid = csp->cp_id;
434 error = SYSCTL_OUT(req, &dout,
sizeof(dout));
438 ICDEBUG(
"%s => %s, %d bytes\n",din.ia_from, din.ia_to, din.ia_datalen);
446 SYSCTL_PROC(_kern_iconv, OID_AUTO, add, CTLFLAG_RW | CTLTYPE_OPAQUE,
473 struct iconv_converter_class *dcp = data;
484 error = ICONV_CONVERTER_INIT(dcp);
491 ICONV_CONVERTER_DONE(dcp);
508 size_t inlen, outlen;
511 if (handle == NULL) {
515 inlen = outlen =
strlen(src);
516 error =
iconv_conv(handle, NULL, NULL, &p, &outlen);
519 error =
iconv_conv(handle, &src, &inlen, &p, &outlen);
531 size_t inlen, outlen;
536 if (handle == NULL) {
537 memcpy(dst, src, size);
540 inlen = outlen = size;
541 error =
iconv_conv(handle, NULL, NULL, &d, &outlen);
544 error =
iconv_conv(handle, &s, &inlen, &d, &outlen);
554 ICDEBUG(
"warning a NULL list passed\n",
"");
571 struct vfsconf *vfsp;
573 vfsp = vfs_byname(fsname);
574 if (vfsp != NULL && vfsp->vfc_refcount > 0)
static int iconv_register_converter(struct iconv_converter_class *dcp)
static int iconv_lookupcs(const char *to, const char *from, struct iconv_cspair **cspp)
MODULE_VERSION(libiconv, 2)
static int iconv_register_cspair(const char *to, const char *from, struct iconv_converter_class *dcp, void *data, struct iconv_cspair **cspp)
size_t strlen(const char *str)
int iconv_lookupcp(char **cpp, const char *s)
static int iconv_sysctl_cslist(SYSCTL_HANDLER_ARGS)
MALLOC_DEFINE(M_ICONV,"iconv","ICONV structures")
struct iconv_cspair * cspfrom
static void iconv_unregister_cspair(struct iconv_cspair *csp)
int iconv_convchr(void *handle, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
SYSCTL_NODE(_kern, OID_AUTO, iconv, CTLFLAG_RW, NULL,"kernel iconv interface")
SYSCTL_PROC(_kern_iconv, OID_AUTO, drvlist, CTLFLAG_RD|CTLTYPE_OPAQUE, NULL, 0, iconv_sysctl_drvlist,"S,xlat","registered converters")
int iconv_converter_handler(module_t mod, int type, void *data)
int iconv_close(void *handle)
int iconv_open(const char *to, const char *from, void **handle)
STATICMETHOD const char * name
static moduledata_t iconv_mod
int iconv_add(const char *converter, const char *to, const char *from)
int towlower(int c, void *handle)
int iconv_converter_initstub(struct iconv_converter_class *dp)
int iconv_vfs_refcount(const char *fsname)
static int iconv_unregister_converter(struct iconv_converter_class *dcp)
int iconv_converter_donestub(struct iconv_converter_class *dp)
static int iconv_sysctl_add(SYSCTL_HANDLER_ARGS)
struct iconv_cspair * cspto
char * iconv_convstr(void *handle, char *dst, const char *src)
int iconv_conv(void *handle, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft)
static TAILQ_HEAD(iconv_converter_list, iconv_converter_class)
DECLARE_MODULE(iconv, iconv_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND)
int towupper(int c, void *handle)
struct sysctl_oid * iconv_oid_hook
int iconv_conv_case(void *handle, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype)
static int iconv_lookupconv(const char *name, struct iconv_converter_class **dcpp)
int strcasecmp(const char *s1, const char *s2)
static int iconv_mod_handler(module_t mod, int type, void *data)
int iconv_convchr_case(void *handle, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype)
static struct sx iconv_lock
char * strcpy(char *__restrict to, const char *__restrict from)
static int iconv_sysctl_drvlist(SYSCTL_HANDLER_ARGS)
INTERFACE iconv_converter
int iconv_converter_tolowerstub(int c, void *handle)
void * iconv_convmem(void *handle, void *dst, const void *src, int size)
int strcmp(const char *s1, const char *s2)