// special iconv for smbd //#include #include typedef struct _iconv_t { int way; // 0 - to ucs, 1 - from ucs UniChar ucp[20]; } *iconv_t; /* Tell "iconv.h" to not define iconv_t by itself. */ #define _ICONV_T #include "includes.h" /* Convert an encoding name to te form understood by UniCreateUconvObject. */ static void __convert_codepage (const char *cp, UniChar *ucp) { size_t sl = 0; if (!stricmp (cp, "SYSTEM")) return; else if (!stricmp (cp, "EUC-JP")) memcpy (ucp, L"IBM-954", 8*2); else if (!stricmp (cp, "EUC-KR")) memcpy (ucp, L"IBM-970", 8*2); else if (!stricmp (cp, "EUC-TW")) memcpy (ucp, L"IBM-964", 8*2); else if (!stricmp (cp, "EUC-CN")) memcpy (ucp, L"IBM-1383", 9*2); else if (!stricmp (cp, "BIG5")) memcpy (ucp, L"IBM-950", 8*2); else if (!stricmp (cp, "UCS-2LE")) memcpy (ucp, L"IBM-1200", 9*2); else { /* Transform CPXXX naming style to IBM-XXX style */ if ((cp[0] == 'C' || cp[0] == 'c') && (cp[1] == 'P' || cp[1] == 'p')) { ucp[sl++] = 'I'; ucp[sl++] = 'B'; ucp[sl++] = 'M'; ucp[sl++] = '-'; cp += 2; } while (*cp != '\0') ucp[sl++] = *cp++; ucp[sl] = 0; } } iconv_t iconv_open (const char *cp_to, const char *cp_from) { UniChar *ucp; char * cp; iconv_t conv; uconv_attribute_t attr; UconvObject uo; if (!cp_to || !cp_from) { errno = EINVAL; return (iconv_t)(-1); } conv = (iconv_t)calloc(sizeof (struct _iconv_t), 1); if (conv == NULL) { errno = ENOMEM; return (iconv_t)(-1); } if (!stricmp (cp_to, "UCS-2LE")) { cp = (char *)cp_from; conv->way = 0; } else if (!stricmp (cp_from, "UCS-2LE")) { cp = (char *)cp_to; conv->way = 1; } else { // samba never calls so errno = EINVAL; return (iconv_t)(-1); } __convert_codepage(cp, conv->ucp); if (UniCreateUconvObject(conv->ucp, &uo)) { free (conv); errno = EINVAL; return (iconv_t)(-1); } UniFreeUconvObject(uo); return conv; } size_t iconv (iconv_t conv, char **in, size_t *in_left, char **out, size_t *out_left) { int rc; size_t sl; size_t retval = 0; UconvObject uo; /* The caller wishes to reset iconv state by calling iconv(conv, NULL, NULL, NULL, NULL). We should handle it */ if (!in || !in_left || !out || !out_left) { return 0; } if (UniCreateUconvObject(conv->ucp, &uo)) { errno = EINVAL; return (size_t)(-1); } if (conv->way) { sl = (*in_left) >> 1; rc = UniUconvFromUcs (uo, (UniChar **)in, &sl, (void **)out, out_left, &retval); *in_left = sl << 1; } else { sl = (*out_left) >> 1; rc = UniUconvToUcs (uo, (void **)in, in_left, (UniChar **)out, &sl, &retval); *out_left = sl << 1; } UniFreeUconvObject(uo); if (!rc) { return retval; } switch (rc) { case ULS_ILLEGALSEQUENCE: errno = ESPIPE; break; case ULS_INVALID: errno = EINVAL; break; case ULS_BUFFERFULL: errno = E2BIG; break; default: errno = EBADF; break; } return (size_t)(-1); } int iconv_close (iconv_t conv) { if (conv && conv != (iconv_t)(-1)) { free (conv); } return 0; }