diff options
author | Jeremy Allison <jra@samba.org> | 2004-08-30 21:35:43 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:52:32 -0500 |
commit | 651daa4b4256455b26b0affcdc45fe328b128c99 (patch) | |
tree | 90abd017d3dd931fb128aecef300e6424b9f8179 /source3 | |
parent | f1688d61df13aacb0e512fd16504cc94f803d808 (diff) | |
download | samba-651daa4b4256455b26b0affcdc45fe328b128c99.tar.gz samba-651daa4b4256455b26b0affcdc45fe328b128c99.tar.bz2 samba-651daa4b4256455b26b0affcdc45fe328b128c99.zip |
r2114: Shameless theft of iconv commit from Samba4 to keep the two libs more in sync :-).
try to cope with a wider range of UTF-16 characters when we are using
an external libiconv library.
Jeremy.
(This used to be commit 5d04cd6804f6fc3b556e7c3b53fa0d7af39797c1)
Diffstat (limited to 'source3')
-rw-r--r-- | source3/include/charset.h | 9 | ||||
-rw-r--r-- | source3/include/smb.h | 6 | ||||
-rw-r--r-- | source3/lib/charcnv.c | 10 | ||||
-rw-r--r-- | source3/lib/iconv.c | 79 | ||||
-rw-r--r-- | source3/modules/weird.c | 4 |
5 files changed, 69 insertions, 39 deletions
diff --git a/source3/include/charset.h b/source3/include/charset.h index 7a9b12ef55..c5d03a62e8 100644 --- a/source3/include/charset.h +++ b/source3/include/charset.h @@ -31,9 +31,9 @@ typedef enum {CH_UCS2=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4} charset_t struct charset_functions { const char *name; - size_t (*pull)(void *, char **inbuf, size_t *inbytesleft, + size_t (*pull)(void *, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); - size_t (*push)(void *, char **inbuf, size_t *inbytesleft, + size_t (*push)(void *, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); struct charset_functions *prev, *next; }; @@ -57,7 +57,7 @@ struct charset_gap_table { * * */ #define SMB_GENERATE_CHARSET_MODULE_8_BIT_GAP(CHARSETNAME) \ -static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft, \ +static size_t CHARSETNAME ## _push(void *cd, const char **inbuf, size_t *inbytesleft, \ char **outbuf, size_t *outbytesleft) \ { \ while (*inbytesleft >= 2 && *outbytesleft >= 1) { \ @@ -97,7 +97,7 @@ static size_t CHARSETNAME ## _push(void *cd, char **inbuf, size_t *inbytesleft, return 0; \ } \ \ -static size_t CHARSETNAME ## _pull(void *cd, char **inbuf, size_t *inbytesleft, \ +static size_t CHARSETNAME ## _pull(void *cd, const char **inbuf, size_t *inbytesleft, \ char **outbuf, size_t *outbytesleft) \ { \ while (*inbytesleft >= 1 && *outbytesleft >= 2) { \ @@ -124,4 +124,3 @@ NTSTATUS charset_ ## CHARSETNAME ## _init(void) \ return smb_register_charset(& CHARSETNAME ## _functions); \ } \ - diff --git a/source3/include/smb.h b/source3/include/smb.h index 32dba0cf78..7317fd16b0 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -1658,11 +1658,11 @@ struct unix_error_map { /* generic iconv conversion structure */ typedef struct { - size_t (*direct)(void *cd, char **inbuf, size_t *inbytesleft, + size_t (*direct)(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); - size_t (*pull)(void *cd, char **inbuf, size_t *inbytesleft, + size_t (*pull)(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); - size_t (*push)(void *cd, char **inbuf, size_t *inbytesleft, + size_t (*push)(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft); void *cd_direct, *cd_pull, *cd_push; char *from_name, *to_name; diff --git a/source3/lib/charcnv.c b/source3/lib/charcnv.c index 6cbf7562b0..21d34f30cb 100644 --- a/source3/lib/charcnv.c +++ b/source3/lib/charcnv.c @@ -56,7 +56,7 @@ static const char *charset_name(charset_t ch) { const char *ret = NULL; - if (ch == CH_UCS2) ret = "UCS-2LE"; + if (ch == CH_UCS2) ret = "UTF-16LE"; else if (ch == CH_UNIX) ret = lp_unix_charset(); else if (ch == CH_DOS) ret = lp_dos_charset(); else if (ch == CH_DISPLAY) ret = lp_display_charset(); @@ -116,10 +116,10 @@ void init_iconv(void) /* so that charset_name() works we need to get the UNIX<->UCS2 going first */ if (!conv_handles[CH_UNIX][CH_UCS2]) - conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII"); + conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open(charset_name(CH_UCS2), "ASCII"); if (!conv_handles[CH_UCS2][CH_UNIX]) - conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE"); + conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UCS2)); for (c1=0;c1<NUM_CHARSETS;c1++) { for (c2=0;c2<NUM_CHARSETS;c2++) { @@ -216,7 +216,7 @@ static size_t convert_string_internal(charset_t from, charset_t to, again: - retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len); + retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len); if(retval==(size_t)-1) { const char *reason="unknown error"; switch(errno) { @@ -531,7 +531,7 @@ size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to, again: retval = smb_iconv(descriptor, - (char **)&inbuf, &i_len, + &inbuf, &i_len, &outbuf, &o_len); if(retval == (size_t)-1) { const char *reason="unknown error"; diff --git a/source3/lib/iconv.c b/source3/lib/iconv.c index 4c9ecf992e..e10e42328c 100644 --- a/source3/lib/iconv.c +++ b/source3/lib/iconv.c @@ -51,18 +51,25 @@ * @sa Samba Developers Guide **/ -static size_t ascii_pull(void *,char **, size_t *, char **, size_t *); -static size_t ascii_push(void *,char **, size_t *, char **, size_t *); -static size_t latin1_push(void *,char **, size_t *, char **, size_t *); -static size_t utf8_pull(void *,char **, size_t *, char **, size_t *); -static size_t utf8_push(void *,char **, size_t *, char **, size_t *); -static size_t ucs2hex_pull(void *,char **, size_t *, char **, size_t *); -static size_t ucs2hex_push(void *,char **, size_t *, char **, size_t *); -static size_t iconv_copy(void *,char **, size_t *, char **, size_t *); +static size_t ascii_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ascii_push(void *,const char **, size_t *, char **, size_t *); +static size_t latin1_push(void *,const char **, size_t *, char **, size_t *); +static size_t utf8_pull(void *,const char **, size_t *, char **, size_t *); +static size_t utf8_push(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_pull(void *,const char **, size_t *, char **, size_t *); +static size_t ucs2hex_push(void *,const char **, size_t *, char **, size_t *); +static size_t iconv_copy(void *,const char **, size_t *, char **, size_t *); +static size_t iconv_swab (void *,const char **, size_t *, char **, size_t *); static struct charset_functions builtin_functions[] = { + /* windows is really neither UCS-2 not UTF-16 */ {"UCS-2LE", iconv_copy, iconv_copy}, + {"UTF-16LE", iconv_copy, iconv_copy}, + {"UCS-2BE", iconv_swab, iconv_swab}, + + /* we include the UTF-8 alias to cope with differing locale settings */ {"UTF8", utf8_pull, utf8_push}, + {"UTF-8", utf8_pull, utf8_push}, {"ASCII", ascii_pull, ascii_push}, {"646", ascii_pull, ascii_push}, {"ISO-8859-1", ascii_pull, latin1_push}, @@ -122,12 +129,12 @@ static void lazy_initialize_iconv(void) this ensures that we don't have a shift state remaining for character sets like SJIS */ static size_t sys_iconv(void *cd, - char **inbuf, size_t *inbytesleft, + const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { #ifdef HAVE_NATIVE_ICONV size_t ret = iconv((iconv_t)cd, - inbuf, inbytesleft, + (char **)inbuf, inbytesleft, outbuf, outbytesleft); if (ret == (size_t)-1) { int saved_errno = errno; @@ -148,7 +155,7 @@ static size_t sys_iconv(void *cd, * enough that Samba works on systems that don't have iconv. **/ size_t smb_iconv(smb_iconv_t cd, - char **inbuf, size_t *inbytesleft, + const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { char cvtbuf[2048]; @@ -158,7 +165,7 @@ size_t smb_iconv(smb_iconv_t cd, /* in many cases we can go direct */ if (cd->direct) { return cd->direct(cd->cd_direct, - (char **)inbuf, inbytesleft, outbuf, outbytesleft); + inbuf, inbytesleft, outbuf, outbytesleft); } @@ -168,14 +175,14 @@ size_t smb_iconv(smb_iconv_t cd, bufsize = sizeof(cvtbuf); if (cd->pull(cd->cd_pull, - (char **)inbuf, inbytesleft, &bufp, &bufsize) == -1 + inbuf, inbytesleft, &bufp, &bufsize) == -1 && errno != E2BIG) return -1; bufp = cvtbuf; bufsize = sizeof(cvtbuf) - bufsize; if (cd->push(cd->cd_push, - &bufp, &bufsize, + (const char **)&bufp, &bufsize, outbuf, outbytesleft) == -1) return -1; } @@ -313,7 +320,7 @@ int smb_iconv_close (smb_iconv_t cd) multi-byte character set support for english users ***********************************************************************/ -static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ascii_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { @@ -333,7 +340,7 @@ static size_t ascii_pull(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ascii_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int ir_count=0; @@ -360,7 +367,7 @@ static size_t ascii_push(void *cd, char **inbuf, size_t *inbytesleft, return ir_count; } -static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t latin1_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int ir_count=0; @@ -387,7 +394,7 @@ static size_t latin1_push(void *cd, char **inbuf, size_t *inbytesleft, return ir_count; } -static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ucs2hex_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { @@ -430,7 +437,7 @@ static size_t ucs2hex_pull(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t ucs2hex_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 2 && *outbytesleft >= 1) { @@ -471,8 +478,32 @@ static size_t ucs2hex_push(void *cd, char **inbuf, size_t *inbytesleft, return 0; } +static size_t iconv_swab(void *cd, const char **inbuf, size_t *inbytesleft, + char **outbuf, size_t *outbytesleft) +{ + int n; + + n = MIN(*inbytesleft, *outbytesleft); + + swab(*inbuf, *outbuf, (n&~1)); + if (n&1) { + (*outbuf)[n-1] = 0; + } + + (*inbytesleft) -= n; + (*outbytesleft) -= n; + (*inbuf) += n; + (*outbuf) += n; + + if (*inbytesleft > 0) { + errno = E2BIG; + return -1; + } + + return 0; +} -static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft, +static size_t iconv_copy(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int n; @@ -494,11 +525,11 @@ static size_t iconv_copy(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t utf8_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t utf8_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { - unsigned char *c = (unsigned char *)*inbuf; + const unsigned char *c = (const unsigned char *)*inbuf; unsigned char *uc = (unsigned char *)*outbuf; int len = 1; @@ -541,12 +572,12 @@ badseq: return -1; } -static size_t utf8_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t utf8_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 2 && *outbytesleft >= 1) { unsigned char *c = (unsigned char *)*outbuf; - unsigned char *uc = (unsigned char *)*inbuf; + const unsigned char *uc = (const unsigned char *)*inbuf; int len=1; if (uc[1] & 0xf8) { diff --git a/source3/modules/weird.c b/source3/modules/weird.c index 444853f383..3c59fd9d61 100644 --- a/source3/modules/weird.c +++ b/source3/modules/weird.c @@ -31,7 +31,7 @@ static struct { {0, NULL} }; -static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft, +static size_t weird_pull(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { while (*inbytesleft >= 1 && *outbytesleft >= 2) { @@ -74,7 +74,7 @@ static size_t weird_pull(void *cd, char **inbuf, size_t *inbytesleft, return 0; } -static size_t weird_push(void *cd, char **inbuf, size_t *inbytesleft, +static size_t weird_push(void *cd, const char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft) { int ir_count=0; |