iconv.c revision 206361
155682Smarkm/*- 255682Smarkm * Copyright (c) 2000-2001 Boris Popov 355682Smarkm * All rights reserved. 455682Smarkm * 555682Smarkm * Redistribution and use in source and binary forms, with or without 655682Smarkm * modification, are permitted provided that the following conditions 755682Smarkm * are met: 855682Smarkm * 1. Redistributions of source code must retain the above copyright 955682Smarkm * notice, this list of conditions and the following disclaimer. 1055682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer in the 1255682Smarkm * documentation and/or other materials provided with the distribution. 1355682Smarkm * 1455682Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1555682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1655682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1755682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1855682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1955682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2055682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2155682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2255682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2355682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2455682Smarkm * SUCH DAMAGE. 2555682Smarkm */ 2655682Smarkm 2755682Smarkm#include <sys/cdefs.h> 2855682Smarkm__FBSDID("$FreeBSD: head/sys/libkern/iconv.c 206361 2010-04-07 16:50:38Z joel $"); 2955682Smarkm 3055682Smarkm#include <sys/param.h> 3155682Smarkm#include <sys/systm.h> 3255682Smarkm#include <sys/kernel.h> 3355682Smarkm#include <sys/iconv.h> 3455682Smarkm#include <sys/malloc.h> 3555682Smarkm#include <sys/mount.h> 3655682Smarkm#include <sys/sx.h> 3755682Smarkm#include <sys/syslog.h> 3855682Smarkm 3955682Smarkm#include "iconv_converter_if.h" 4055682Smarkm 4155682SmarkmSYSCTL_DECL(_kern_iconv); 4255682Smarkm 4355682SmarkmSYSCTL_NODE(_kern, OID_AUTO, iconv, CTLFLAG_RW, NULL, "kernel iconv interface"); 4455682Smarkm 4555682SmarkmMALLOC_DEFINE(M_ICONV, "iconv", "ICONV structures"); 4655682SmarkmMALLOC_DEFINE(M_ICONVDATA, "iconv_data", "ICONV data"); 4755682Smarkm 4855682SmarkmMODULE_VERSION(libiconv, 2); 4955682Smarkm 5055682Smarkmstatic struct sx iconv_lock; 5155682Smarkm 5255682Smarkm#ifdef notnow 5355682Smarkm/* 5455682Smarkm * iconv converter instance 5555682Smarkm */ 5655682Smarkmstruct iconv_converter { 5755682Smarkm KOBJ_FIELDS; 5855682Smarkm void * c_data; 5955682Smarkm}; 6055682Smarkm#endif 6155682Smarkm 6255682Smarkmstruct sysctl_oid *iconv_oid_hook = &sysctl___kern_iconv; 6355682Smarkm 6455682Smarkm/* 6555682Smarkm * List of loaded converters 6655682Smarkm */ 6755682Smarkmstatic TAILQ_HEAD(iconv_converter_list, iconv_converter_class) 6855682Smarkm iconv_converters = TAILQ_HEAD_INITIALIZER(iconv_converters); 6955682Smarkm 7055682Smarkm/* 7155682Smarkm * List of supported/loaded charsets pairs 7255682Smarkm */ 7355682Smarkmstatic TAILQ_HEAD(, iconv_cspair) 7455682Smarkm iconv_cslist = TAILQ_HEAD_INITIALIZER(iconv_cslist); 7555682Smarkmstatic int iconv_csid = 1; 7655682Smarkm 7755682Smarkmstatic char iconv_unicode_string[] = "unicode"; /* save eight bytes when possible */ 7855682Smarkm 7955682Smarkmstatic void iconv_unregister_cspair(struct iconv_cspair *csp); 8055682Smarkm 8155682Smarkmstatic int 8255682Smarkmiconv_mod_unload(void) 8355682Smarkm{ 8455682Smarkm struct iconv_cspair *csp; 8555682Smarkm 8655682Smarkm sx_xlock(&iconv_lock); 8755682Smarkm while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) { 8855682Smarkm if (csp->cp_refcount) 8955682Smarkm return EBUSY; 9055682Smarkm } 9155682Smarkm 9255682Smarkm while ((csp = TAILQ_FIRST(&iconv_cslist)) != NULL) 9355682Smarkm iconv_unregister_cspair(csp); 9455682Smarkm sx_xunlock(&iconv_lock); 9555682Smarkm sx_destroy(&iconv_lock); 9655682Smarkm return 0; 9755682Smarkm} 9855682Smarkm 9955682Smarkmstatic int 10055682Smarkmiconv_mod_handler(module_t mod, int type, void *data) 10155682Smarkm{ 10255682Smarkm int error; 10355682Smarkm 10455682Smarkm switch (type) { 10555682Smarkm case MOD_LOAD: 10655682Smarkm error = 0; 10755682Smarkm sx_init(&iconv_lock, "iconv"); 10855682Smarkm break; 10955682Smarkm case MOD_UNLOAD: 11055682Smarkm error = iconv_mod_unload(); 11155682Smarkm break; 11255682Smarkm default: 11355682Smarkm error = EINVAL; 11455682Smarkm } 11555682Smarkm return error; 11655682Smarkm} 11755682Smarkm 11855682Smarkmstatic moduledata_t iconv_mod = { 11955682Smarkm "iconv", iconv_mod_handler, NULL 12055682Smarkm}; 12155682Smarkm 12255682SmarkmDECLARE_MODULE(iconv, iconv_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 12355682Smarkm 12455682Smarkmstatic int 12555682Smarkmiconv_register_converter(struct iconv_converter_class *dcp) 12655682Smarkm{ 12755682Smarkm kobj_class_compile((struct kobj_class*)dcp); 12855682Smarkm dcp->refs++; 12955682Smarkm TAILQ_INSERT_TAIL(&iconv_converters, dcp, cc_link); 13055682Smarkm return 0; 13155682Smarkm} 13255682Smarkm 13355682Smarkmstatic int 13455682Smarkmiconv_unregister_converter(struct iconv_converter_class *dcp) 13555682Smarkm{ 13655682Smarkm if (dcp->refs > 1) { 13755682Smarkm ICDEBUG("converter have %d referenses left\n", dcp->refs); 13855682Smarkm return EBUSY; 13955682Smarkm } 14055682Smarkm TAILQ_REMOVE(&iconv_converters, dcp, cc_link); 14155682Smarkm kobj_class_free((struct kobj_class*)dcp); 14255682Smarkm return 0; 14355682Smarkm} 14455682Smarkm 14555682Smarkmstatic int 14655682Smarkmiconv_lookupconv(const char *name, struct iconv_converter_class **dcpp) 14755682Smarkm{ 14855682Smarkm struct iconv_converter_class *dcp; 14955682Smarkm 15055682Smarkm TAILQ_FOREACH(dcp, &iconv_converters, cc_link) { 15155682Smarkm if (name == NULL) 15255682Smarkm continue; 15355682Smarkm if (strcmp(name, ICONV_CONVERTER_NAME(dcp)) == 0) { 15455682Smarkm if (dcpp) 15555682Smarkm *dcpp = dcp; 15655682Smarkm return 0; 15755682Smarkm } 15855682Smarkm } 15955682Smarkm return ENOENT; 16055682Smarkm} 16155682Smarkm 16255682Smarkmstatic int 16355682Smarkmiconv_lookupcs(const char *to, const char *from, struct iconv_cspair **cspp) 16455682Smarkm{ 16555682Smarkm struct iconv_cspair *csp; 16655682Smarkm 16755682Smarkm TAILQ_FOREACH(csp, &iconv_cslist, cp_link) { 16855682Smarkm if (strcmp(csp->cp_to, to) == 0 && 16955682Smarkm strcmp(csp->cp_from, from) == 0) { 17055682Smarkm if (cspp) 17155682Smarkm *cspp = csp; 17255682Smarkm return 0; 17355682Smarkm } 17455682Smarkm } 17555682Smarkm return ENOENT; 17655682Smarkm} 17755682Smarkm 17855682Smarkmstatic int 17955682Smarkmiconv_register_cspair(const char *to, const char *from, 18055682Smarkm struct iconv_converter_class *dcp, void *data, 18155682Smarkm struct iconv_cspair **cspp) 18255682Smarkm{ 18355682Smarkm struct iconv_cspair *csp; 18455682Smarkm char *cp; 18555682Smarkm int csize, ucsto, ucsfrom; 18655682Smarkm 18755682Smarkm if (iconv_lookupcs(to, from, NULL) == 0) 18855682Smarkm return EEXIST; 18955682Smarkm csize = sizeof(*csp); 19055682Smarkm ucsto = strcmp(to, iconv_unicode_string) == 0; 19155682Smarkm if (!ucsto) 19255682Smarkm csize += strlen(to) + 1; 19355682Smarkm ucsfrom = strcmp(from, iconv_unicode_string) == 0; 19455682Smarkm if (!ucsfrom) 19555682Smarkm csize += strlen(from) + 1; 19655682Smarkm csp = malloc(csize, M_ICONV, M_WAITOK); 19755682Smarkm bzero(csp, csize); 19855682Smarkm csp->cp_id = iconv_csid++; 19955682Smarkm csp->cp_dcp = dcp; 20055682Smarkm cp = (char*)(csp + 1); 20155682Smarkm if (!ucsto) { 20255682Smarkm strcpy(cp, to); 20355682Smarkm csp->cp_to = cp; 20455682Smarkm cp += strlen(cp) + 1; 20555682Smarkm } else 20655682Smarkm csp->cp_to = iconv_unicode_string; 20755682Smarkm if (!ucsfrom) { 20855682Smarkm strcpy(cp, from); 20955682Smarkm csp->cp_from = cp; 21055682Smarkm } else 21155682Smarkm csp->cp_from = iconv_unicode_string; 21255682Smarkm csp->cp_data = data; 21355682Smarkm 21455682Smarkm TAILQ_INSERT_TAIL(&iconv_cslist, csp, cp_link); 21555682Smarkm *cspp = csp; 21655682Smarkm return 0; 21755682Smarkm} 21855682Smarkm 21955682Smarkmstatic void 22055682Smarkmiconv_unregister_cspair(struct iconv_cspair *csp) 22155682Smarkm{ 22255682Smarkm TAILQ_REMOVE(&iconv_cslist, csp, cp_link); 22355682Smarkm if (csp->cp_data) 22455682Smarkm free(csp->cp_data, M_ICONVDATA); 22555682Smarkm free(csp, M_ICONV); 22655682Smarkm} 22755682Smarkm 22855682Smarkm/* 22955682Smarkm * Lookup and create an instance of converter. 23055682Smarkm * Currently this layer didn't have associated 'instance' structure 23155682Smarkm * to avoid unnesessary memory allocation. 23255682Smarkm */ 23355682Smarkmint 23455682Smarkmiconv_open(const char *to, const char *from, void **handle) 23555682Smarkm{ 23655682Smarkm struct iconv_cspair *csp, *cspfrom, *cspto; 23755682Smarkm struct iconv_converter_class *dcp; 23855682Smarkm const char *cnvname; 23955682Smarkm int error; 24055682Smarkm 24155682Smarkm /* 24255682Smarkm * First, lookup fully qualified cspairs 24355682Smarkm */ 24455682Smarkm error = iconv_lookupcs(to, from, &csp); 24555682Smarkm if (error == 0) 24655682Smarkm return ICONV_CONVERTER_OPEN(csp->cp_dcp, csp, NULL, handle); 24755682Smarkm 24855682Smarkm /* 24955682Smarkm * Well, nothing found. Now try to construct a composite conversion 25055682Smarkm * ToDo: add a 'capability' field to converter 25155682Smarkm */ 25255682Smarkm TAILQ_FOREACH(dcp, &iconv_converters, cc_link) { 25355682Smarkm cnvname = ICONV_CONVERTER_NAME(dcp); 25455682Smarkm if (cnvname == NULL) 25555682Smarkm continue; 25655682Smarkm error = iconv_lookupcs(cnvname, from, &cspfrom); 25755682Smarkm if (error) 25855682Smarkm continue; 25955682Smarkm error = iconv_lookupcs(to, cnvname, &cspto); 26055682Smarkm if (error) 26155682Smarkm continue; 26255682Smarkm /* 26355682Smarkm * Fine, we're found a pair which can be combined together 26455682Smarkm */ 26555682Smarkm return ICONV_CONVERTER_OPEN(dcp, cspto, cspfrom, handle); 26655682Smarkm } 26755682Smarkm return ENOENT; 26855682Smarkm} 26955682Smarkm 27055682Smarkmint 27155682Smarkmiconv_close(void *handle) 27255682Smarkm{ 27355682Smarkm return ICONV_CONVERTER_CLOSE(handle); 27455682Smarkm} 27555682Smarkm 27655682Smarkmint 27755682Smarkmiconv_conv(void *handle, const char **inbuf, 27855682Smarkm size_t *inbytesleft, char **outbuf, size_t *outbytesleft) 27955682Smarkm{ 28055682Smarkm return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 0, 0); 28155682Smarkm} 28255682Smarkm 28355682Smarkmint 28455682Smarkmiconv_conv_case(void *handle, const char **inbuf, 28555682Smarkm size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype) 28655682Smarkm{ 28755682Smarkm return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 0, casetype); 28855682Smarkm} 28955682Smarkm 29055682Smarkmint 29155682Smarkmiconv_convchr(void *handle, const char **inbuf, 29255682Smarkm size_t *inbytesleft, char **outbuf, size_t *outbytesleft) 29355682Smarkm{ 29455682Smarkm return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 1, 0); 29555682Smarkm} 29655682Smarkm 29755682Smarkmint 29855682Smarkmiconv_convchr_case(void *handle, const char **inbuf, 29955682Smarkm size_t *inbytesleft, char **outbuf, size_t *outbytesleft, int casetype) 30055682Smarkm{ 30155682Smarkm return ICONV_CONVERTER_CONV(handle, inbuf, inbytesleft, outbuf, outbytesleft, 1, casetype); 30255682Smarkm} 30355682Smarkm 30455682Smarkmint 30555682Smarkmtowlower(int c, void *handle) 30655682Smarkm{ 30755682Smarkm return ICONV_CONVERTER_TOLOWER(handle, c); 30855682Smarkm} 30955682Smarkm 31055682Smarkmint 31155682Smarkmtowupper(int c, void *handle) 31255682Smarkm{ 31355682Smarkm return ICONV_CONVERTER_TOUPPER(handle, c); 31455682Smarkm} 31555682Smarkm 31655682Smarkm/* 31755682Smarkm * Give a list of loaded converters. Each name terminated with 0. 31855682Smarkm * An empty string terminates the list. 31955682Smarkm */ 32055682Smarkmstatic int 32155682Smarkmiconv_sysctl_drvlist(SYSCTL_HANDLER_ARGS) 32255682Smarkm{ 32355682Smarkm struct iconv_converter_class *dcp; 32455682Smarkm const char *name; 32555682Smarkm char spc; 32655682Smarkm int error; 32755682Smarkm 32855682Smarkm error = 0; 32955682Smarkm sx_slock(&iconv_lock); 33055682Smarkm TAILQ_FOREACH(dcp, &iconv_converters, cc_link) { 33155682Smarkm name = ICONV_CONVERTER_NAME(dcp); 33255682Smarkm if (name == NULL) 33355682Smarkm continue; 33455682Smarkm error = SYSCTL_OUT(req, name, strlen(name) + 1); 33555682Smarkm if (error) 33655682Smarkm break; 33755682Smarkm } 33855682Smarkm sx_sunlock(&iconv_lock); 33955682Smarkm if (error) 34055682Smarkm return error; 34155682Smarkm spc = 0; 34255682Smarkm error = SYSCTL_OUT(req, &spc, sizeof(spc)); 34355682Smarkm return error; 34455682Smarkm} 34555682Smarkm 34655682SmarkmSYSCTL_PROC(_kern_iconv, OID_AUTO, drvlist, CTLFLAG_RD | CTLTYPE_OPAQUE, 34755682Smarkm NULL, 0, iconv_sysctl_drvlist, "S,xlat", "registered converters"); 34855682Smarkm 34955682Smarkm/* 35055682Smarkm * List all available charset pairs. 35155682Smarkm */ 35255682Smarkmstatic int 35355682Smarkmiconv_sysctl_cslist(SYSCTL_HANDLER_ARGS) 35455682Smarkm{ 35555682Smarkm struct iconv_cspair *csp; 35655682Smarkm struct iconv_cspair_info csi; 35755682Smarkm int error; 35855682Smarkm 35955682Smarkm error = 0; 36055682Smarkm bzero(&csi, sizeof(csi)); 36155682Smarkm csi.cs_version = ICONV_CSPAIR_INFO_VER; 36255682Smarkm sx_slock(&iconv_lock); 36355682Smarkm TAILQ_FOREACH(csp, &iconv_cslist, cp_link) { 36455682Smarkm csi.cs_id = csp->cp_id; 36555682Smarkm csi.cs_refcount = csp->cp_refcount; 36655682Smarkm csi.cs_base = csp->cp_base ? csp->cp_base->cp_id : 0; 36755682Smarkm strcpy(csi.cs_to, csp->cp_to); 36855682Smarkm strcpy(csi.cs_from, csp->cp_from); 36955682Smarkm error = SYSCTL_OUT(req, &csi, sizeof(csi)); 37055682Smarkm if (error) 37155682Smarkm break; 37255682Smarkm } 37355682Smarkm sx_sunlock(&iconv_lock); 37455682Smarkm return error; 37555682Smarkm} 37655682Smarkm 37755682SmarkmSYSCTL_PROC(_kern_iconv, OID_AUTO, cslist, CTLFLAG_RD | CTLTYPE_OPAQUE, 37855682Smarkm NULL, 0, iconv_sysctl_cslist, "S,xlat", "registered charset pairs"); 37955682Smarkm 38055682Smarkm/* 38155682Smarkm * Add new charset pair 38255682Smarkm */ 38355682Smarkmstatic int 38455682Smarkmiconv_sysctl_add(SYSCTL_HANDLER_ARGS) 38555682Smarkm{ 38655682Smarkm struct iconv_converter_class *dcp; 38755682Smarkm struct iconv_cspair *csp; 38855682Smarkm struct iconv_add_in din; 38955682Smarkm struct iconv_add_out dout; 39055682Smarkm int error; 39155682Smarkm 39255682Smarkm error = SYSCTL_IN(req, &din, sizeof(din)); 39355682Smarkm if (error) 39455682Smarkm return error; 39555682Smarkm if (din.ia_version != ICONV_ADD_VER) 39655682Smarkm return EINVAL; 39755682Smarkm if (din.ia_datalen > ICONV_CSMAXDATALEN) 39855682Smarkm return EINVAL; 39955682Smarkm if (strlen(din.ia_from) >= ICONV_CSNMAXLEN) 40055682Smarkm return EINVAL; 40155682Smarkm if (strlen(din.ia_to) >= ICONV_CSNMAXLEN) 40255682Smarkm return EINVAL; 40355682Smarkm if (strlen(din.ia_converter) >= ICONV_CNVNMAXLEN) 40455682Smarkm return EINVAL; 40555682Smarkm if (iconv_lookupconv(din.ia_converter, &dcp) != 0) 40655682Smarkm return EINVAL; 40755682Smarkm sx_xlock(&iconv_lock); 40855682Smarkm error = iconv_register_cspair(din.ia_to, din.ia_from, dcp, NULL, &csp); 40955682Smarkm if (error) { 41055682Smarkm sx_xunlock(&iconv_lock); 41155682Smarkm return error; 41255682Smarkm } 41355682Smarkm if (din.ia_datalen) { 41455682Smarkm csp->cp_data = malloc(din.ia_datalen, M_ICONVDATA, M_WAITOK); 41555682Smarkm error = copyin(din.ia_data, csp->cp_data, din.ia_datalen); 41655682Smarkm if (error) 41755682Smarkm goto bad; 41855682Smarkm } 41955682Smarkm dout.ia_csid = csp->cp_id; 42055682Smarkm error = SYSCTL_OUT(req, &dout, sizeof(dout)); 42155682Smarkm if (error) 42255682Smarkm goto bad; 42355682Smarkm sx_xunlock(&iconv_lock); 42455682Smarkm ICDEBUG("%s => %s, %d bytes\n",din.ia_from, din.ia_to, din.ia_datalen); 42555682Smarkm return 0; 42655682Smarkmbad: 42755682Smarkm iconv_unregister_cspair(csp); 42855682Smarkm sx_xunlock(&iconv_lock); 42955682Smarkm return error; 43055682Smarkm} 43155682Smarkm 43255682SmarkmSYSCTL_PROC(_kern_iconv, OID_AUTO, add, CTLFLAG_RW | CTLTYPE_OPAQUE, 43355682Smarkm NULL, 0, iconv_sysctl_add, "S,xlat", "register charset pair"); 43455682Smarkm 43555682Smarkm/* 43655682Smarkm * Default stubs for converters 43755682Smarkm */ 43855682Smarkmint 43955682Smarkmiconv_converter_initstub(struct iconv_converter_class *dp) 44055682Smarkm{ 44155682Smarkm return 0; 44255682Smarkm} 44355682Smarkm 44455682Smarkmint 44555682Smarkmiconv_converter_donestub(struct iconv_converter_class *dp) 44655682Smarkm{ 44755682Smarkm return 0; 44855682Smarkm} 44955682Smarkm 45055682Smarkmint 45155682Smarkmiconv_converter_tolowerstub(int c, void *handle) 45255682Smarkm{ 45355682Smarkm return (c); 45455682Smarkm} 45555682Smarkm 45655682Smarkmint 45755682Smarkmiconv_converter_handler(module_t mod, int type, void *data) 45855682Smarkm{ 45955682Smarkm struct iconv_converter_class *dcp = data; 46055682Smarkm int error; 46155682Smarkm 46255682Smarkm switch (type) { 46355682Smarkm case MOD_LOAD: 46455682Smarkm sx_xlock(&iconv_lock); 46555682Smarkm error = iconv_register_converter(dcp); 46655682Smarkm if (error) { 46755682Smarkm sx_xunlock(&iconv_lock); 46855682Smarkm break; 46955682Smarkm } 47055682Smarkm error = ICONV_CONVERTER_INIT(dcp); 47155682Smarkm if (error) 47255682Smarkm iconv_unregister_converter(dcp); 47355682Smarkm sx_xunlock(&iconv_lock); 47455682Smarkm break; 47555682Smarkm case MOD_UNLOAD: 47655682Smarkm sx_xlock(&iconv_lock); 47755682Smarkm ICONV_CONVERTER_DONE(dcp); 47855682Smarkm error = iconv_unregister_converter(dcp); 47955682Smarkm sx_xunlock(&iconv_lock); 48055682Smarkm break; 48155682Smarkm default: 48255682Smarkm error = EINVAL; 48355682Smarkm } 48455682Smarkm return error; 48555682Smarkm} 48655682Smarkm 48755682Smarkm/* 48855682Smarkm * Common used functions (don't use with unicode) 48955682Smarkm */ 49055682Smarkmchar * 49155682Smarkmiconv_convstr(void *handle, char *dst, const char *src) 49255682Smarkm{ 49355682Smarkm char *p = dst; 49455682Smarkm size_t inlen, outlen; 49555682Smarkm int error; 49655682Smarkm 49755682Smarkm if (handle == NULL) { 49855682Smarkm strcpy(dst, src); 49955682Smarkm return dst; 50055682Smarkm } 50155682Smarkm inlen = outlen = strlen(src); 50255682Smarkm error = iconv_conv(handle, NULL, NULL, &p, &outlen); 50355682Smarkm if (error) 50455682Smarkm return NULL; 50555682Smarkm error = iconv_conv(handle, &src, &inlen, &p, &outlen); 50655682Smarkm if (error) 50755682Smarkm return NULL; 50855682Smarkm *p = 0; 50955682Smarkm return dst; 51055682Smarkm} 51155682Smarkm 51255682Smarkmvoid * 51355682Smarkmiconv_convmem(void *handle, void *dst, const void *src, int size) 51455682Smarkm{ 51555682Smarkm const char *s = src; 51655682Smarkm char *d = dst; 51755682Smarkm size_t inlen, outlen; 51855682Smarkm int error; 51955682Smarkm 52055682Smarkm if (size == 0) 52155682Smarkm return dst; 52255682Smarkm if (handle == NULL) { 52355682Smarkm memcpy(dst, src, size); 52455682Smarkm return dst; 52555682Smarkm } 52655682Smarkm inlen = outlen = size; 52755682Smarkm error = iconv_conv(handle, NULL, NULL, &d, &outlen); 52855682Smarkm if (error) 52955682Smarkm return NULL; 53055682Smarkm error = iconv_conv(handle, &s, &inlen, &d, &outlen); 53155682Smarkm if (error) 53255682Smarkm return NULL; 53355682Smarkm return dst; 53455682Smarkm} 53555682Smarkm 53655682Smarkmint 53755682Smarkmiconv_lookupcp(char **cpp, const char *s) 53855682Smarkm{ 53955682Smarkm if (cpp == NULL) { 54055682Smarkm ICDEBUG("warning a NULL list passed\n", ""); /* XXX ISO variadic macros cannot 54155682Smarkm leave out the 54255682Smarkm variadic args */ 54355682Smarkm return ENOENT; 54455682Smarkm } 54555682Smarkm for (; *cpp; cpp++) 54655682Smarkm if (strcmp(*cpp, s) == 0) 54755682Smarkm return 0; 54855682Smarkm return ENOENT; 54955682Smarkm} 55055682Smarkm 55155682Smarkm/* 55255682Smarkm * Return if fsname is in use of not 55355682Smarkm */ 55455682Smarkmint 55555682Smarkmiconv_vfs_refcount(const char *fsname) 55655682Smarkm{ 55755682Smarkm struct vfsconf *vfsp; 55855682Smarkm 55955682Smarkm vfsp = vfs_byname(fsname); 56055682Smarkm if (vfsp != NULL && vfsp->vfc_refcount > 0) 56155682Smarkm return (EBUSY); 56255682Smarkm return (0); 56355682Smarkm} 56455682Smarkm