📄 charcnv.c
字号:
retval += 2; if (!lastp) break; } else {#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS goto general_case;#else return retval + convert_string_internal(from, to, p, slen, q, dlen, allow_bad_conv);#endif } } if (!dlen) { /* Even if we fast path we should note if we ran out of room. */ if (((slen != (size_t)-1) && slen) || ((slen == (size_t)-1) && lastp)) { errno = E2BIG; } } return retval; }#ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS general_case:#endif return convert_string_internal(from, to, src, srclen, dest, destlen, allow_bad_conv);}/** * Convert between character sets, allocating a new buffer for the result. * * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc. * @param srclen length of source buffer. * @param dest always set at least to NULL * @note -1 is not accepted for srclen. * * @returns Size in bytes of the converted string; or -1 in case of error. * * Ensure the srclen contains the terminating zero. * * I hate the goto's in this function. It's embarressing..... * There has to be a cleaner way to do this. JRA. **/size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest, BOOL allow_bad_conv){ size_t i_len, o_len, destlen = MAX(srclen, 512); size_t retval; const char *inbuf = (const char *)src; char *outbuf = NULL, *ob = NULL; smb_iconv_t descriptor; *dest = NULL; if (src == NULL || srclen == (size_t)-1) return (size_t)-1; if (srclen == 0) return 0; lazy_initialize_conv(); descriptor = conv_handles[from][to]; if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) { if (!conv_silent) DEBUG(0,("convert_string_allocate: Conversion not supported.\n")); return (size_t)-1; } convert: if ((destlen*2) < destlen) { /* wrapped ! abort. */ if (!conv_silent) DEBUG(0, ("convert_string_allocate: destlen wrapped !\n")); if (!ctx) SAFE_FREE(outbuf); return (size_t)-1; } else { destlen = destlen * 2; } if (ctx) ob = (char *)TALLOC_REALLOC(ctx, ob, destlen); else ob = (char *)SMB_REALLOC(ob, destlen); if (!ob) { DEBUG(0, ("convert_string_allocate: realloc failed!\n")); if (!ctx) SAFE_FREE(outbuf); return (size_t)-1; } else { outbuf = ob; } i_len = srclen; o_len = destlen; again: retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); if(retval == (size_t)-1) { const char *reason="unknown error"; switch(errno) { case EINVAL: reason="Incomplete multibyte sequence"; if (!conv_silent) DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf)); if (allow_bad_conv) goto use_as_is; break; case E2BIG: goto convert; case EILSEQ: reason="Illegal multibyte sequence"; if (!conv_silent) DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf)); if (allow_bad_conv) goto use_as_is; break; } if (!conv_silent) DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf)); /* smb_panic(reason); */ return (size_t)-1; } out: destlen = destlen - o_len; if (ctx) *dest = (char *)TALLOC_REALLOC(ctx,ob,destlen); else *dest = (char *)SMB_REALLOC(ob,destlen); if (destlen && !*dest) { DEBUG(0, ("convert_string_allocate: out of memory!\n")); if (!ctx) SAFE_FREE(ob); return (size_t)-1; } return destlen; use_as_is: /* * Conversion not supported. This is actually an error, but there are so * many misconfigured iconv systems and smb.conf's out there we can't just * fail. Do a very bad conversion instead.... JRA. */ { if (o_len == 0 || i_len == 0) goto out; if (from == CH_UCS2 && to != CH_UCS2) { /* Can't convert from ucs2 to multibyte. Just use the default fail char. */ if (i_len < 2) goto out; if (i_len >= 2) { *outbuf = lp_failed_convert_char(); outbuf++; o_len--; inbuf += 2; i_len -= 2; } if (o_len == 0 || i_len == 0) goto out; /* Keep trying with the next char... */ goto again; } else if (from != CH_UCS2 && to == CH_UCS2) { /* Can't convert to ucs2 - just widen by adding the default fail char then zero. */ if (o_len < 2) goto out; outbuf[0] = lp_failed_convert_char(); outbuf[1] = '\0'; inbuf++; i_len--; outbuf += 2; o_len -= 2; if (o_len == 0 || i_len == 0) goto out; /* Keep trying with the next char... */ goto again; } else if (from != CH_UCS2 && to != CH_UCS2) { /* Failed multibyte to multibyte. Just copy the default fail char and try again. */ outbuf[0] = lp_failed_convert_char(); inbuf++; i_len--; outbuf++; o_len--; if (o_len == 0 || i_len == 0) goto out; /* Keep trying with the next char... */ goto again; } else { /* Keep compiler happy.... */ goto out; } }}/** * Convert between character sets, allocating a new buffer using talloc for the result. * * @param srclen length of source buffer. * @param dest always set at least to NULL * @note -1 is not accepted for srclen. * * @returns Size in bytes of the converted string; or -1 in case of error. **/static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to, void const *src, size_t srclen, void **dest, BOOL allow_bad_conv){ size_t dest_len; *dest = NULL; dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest, allow_bad_conv); if (dest_len == (size_t)-1) return (size_t)-1; if (*dest == NULL) return (size_t)-1; return dest_len;}size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen){ size_t size; smb_ucs2_t *buffer; size = push_ucs2_allocate(&buffer, src); if (size == (size_t)-1) { smb_panic("failed to create UCS2 buffer"); } if (!strupper_w(buffer) && (dest == src)) { free(buffer); return srclen; } size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True); free(buffer); return size;}/** strdup() a unix string to upper case. Max size is pstring.**/char *strdup_upper(const char *s){ pstring out_buffer; const unsigned char *p = (const unsigned char *)s; unsigned char *q = (unsigned char *)out_buffer; /* this is quite a common operation, so we want it to be fast. We optimise for the ascii case, knowing that all our supported multi-byte character sets are ascii-compatible (ie. they match for the first 128 chars) */ while (1) { if (*p & 0x80) break; *q++ = toupper_ascii(*p); if (!*p) break; p++; if (p - ( const unsigned char *)s >= sizeof(pstring)) break; } if (*p) { /* MB case. */ size_t size; wpstring buffer; size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer), True); if (size == (size_t)-1) { return NULL; } strupper_w(buffer); size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer), True); if (size == (size_t)-1) { return NULL; } } return SMB_STRDUP(out_buffer);}size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen){ size_t size; smb_ucs2_t *buffer = NULL; size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen, (void **)(void *)&buffer, True); if (size == (size_t)-1 || !buffer) { smb_panic("failed to create UCS2 buffer"); } if (!strlower_w(buffer) && (dest == src)) { SAFE_FREE(buffer); return srclen; } size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen, True); SAFE_FREE(buffer); return size;}/** strdup() a unix string to lower case.**/char *strdup_lower(const char *s){ size_t size; smb_ucs2_t *buffer = NULL; char *out_buffer; size = push_ucs2_allocate(&buffer, s); if (size == -1 || !buffer) { return NULL; } strlower_w(buffer); size = pull_ucs2_allocate(&out_buffer, buffer); SAFE_FREE(buffer); if (size == (size_t)-1) { return NULL; } return out_buffer;}static size_t ucs2_align(const void *base_ptr, const void *p, int flags){ if (flags & (STR_NOALIGN|STR_ASCII)) return 0; return PTR_DIFF(p, base_ptr) & 1;}/** * Copy a string from a char* unix src to a dos codepage string destination. * * @return the number of bytes occupied by the string in the destination. * * @param flags can include * <dl> * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd> * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd> * </dl> * * @param dest_len the maximum length in bytes allowed in the * destination. If @p dest_len is -1 then no maximum is used. **/size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags){ size_t src_len = strlen(src); pstring tmpbuf; /* treat a pstring as "unlimited" length */ if (dest_len == (size_t)-1) dest_len = sizeof(pstring); if (flags & STR_UPPER) { pstrcpy(tmpbuf, src); strupper_m(tmpbuf); src = tmpbuf; } if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII)) src_len++; return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len, True);}size_t push_ascii_fstring(void *dest, const char *src){ return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);}size_t push_ascii_pstring(void *dest, const char *src){ return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);}/******************************************************************** Push an nstring - ensure null terminated. Written by moriyama@miraclelinux.com (MORIYAMA Masayuki).********************************************************************/size_t push_ascii_nstring(void *dest, const char *src){ size_t i, buffer_len, dest_len; smb_ucs2_t *buffer; conv_silent = True; buffer_len = push_ucs2_allocate(&buffer, src); if (buffer_len == (size_t)-1) { smb_panic("failed to create UCS2 buffer"); } /* We're using buffer_len below to count ucs2 characters, not bytes. */ buffer_len /= sizeof(smb_ucs2_t); dest_len = 0; for (i = 0; buffer[i] != 0 && (i < buffer_len); i++) { unsigned char mb[10]; /* Convert one smb_ucs2_t character at a time. */ size_t mb_len = convert_string(CH_UCS2, CH_DOS, buffer+i, sizeof(smb_ucs2_t), mb, sizeof(mb), False); if ((mb_len != (size_t)-1) && (dest_len + mb_len <= MAX_NETBIOSNAME_LEN - 1)) { memcpy((char *)dest + dest_len, mb, mb_len); dest_len += mb_len; } else { errno = E2BIG; break; } } ((char *)dest)[dest_len] = '\0'; SAFE_FREE(buffer); conv_silent = False; return dest_len;}/** * Copy a string from a dos codepage source to a unix char* destination. * * The resulting string in "dest" is always null terminated. * * @param flags can have: * <dl> * <dt>STR_TERMINATE</dt> * <dd>STR_TERMINATE means the string in @p src * is null terminated, and src_len is ignored.</dd> * </dl> * * @param src_len is the length of the source area in bytes. * @returns the number of bytes occupied by the string in @p src. **/size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -