2 Unix SMB/CIFS implementation.
3 Character set conversion Extensions
4 Copyright (C) Igor Vergeichik <iverg@mail.ru> 2001
5 Copyright (C) Andrew Tridgell 2001
6 Copyright (C) Simo Sorce 2001
7 Copyright (C) Martin Pool 2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 /* We can parameterize this if someone complains.... JRA. */
27 char lp_failed_convert_char(void)
35 * @brief Character-set conversion routines built on our iconv.
37 * @note Samba's internal character set (at least in the 3.0 series)
38 * is always the same as the one for the Unix filesystem. It is
39 * <b>not</b> necessarily UTF-8 and may be different on machines that
40 * need i18n filenames to be compatible with Unix software. It does
41 * have to be a superset of ASCII. All multibyte sequences must start
42 * with a byte with the high bit set.
48 static smb_iconv_t conv_handles
[NUM_CHARSETS
][NUM_CHARSETS
];
49 static bool conv_silent
; /* Should we do a debug if the conversion fails ? */
50 static bool initialized
;
53 * Return the name of a charset to give to iconv().
55 static const char *charset_name(charset_t ch
)
67 ret
= lp_unix_charset();
70 ret
= lp_dos_charset();
73 ret
= lp_display_charset();
82 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
83 if (ret
&& !strcmp(ret
, "LOCALE")) {
84 const char *ln
= NULL
;
87 setlocale(LC_ALL
, "");
89 ln
= nl_langinfo(CODESET
);
91 /* Check whether the charset name is supported
93 smb_iconv_t handle
= smb_iconv_open(ln
,"UCS-2LE");
94 if (handle
== (smb_iconv_t
) -1) {
95 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln
));
98 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln
));
99 smb_iconv_close(handle
);
106 if (!ret
|| !*ret
) ret
= "ASCII";
110 void lazy_initialize_conv(void)
120 * Destroy global objects allocated by init_iconv()
122 void gfree_charcnv(void)
126 for (c1
=0;c1
<NUM_CHARSETS
;c1
++) {
127 for (c2
=0;c2
<NUM_CHARSETS
;c2
++) {
128 if ( conv_handles
[c1
][c2
] ) {
129 smb_iconv_close( conv_handles
[c1
][c2
] );
130 conv_handles
[c1
][c2
] = 0;
138 * Initialize iconv conversion descriptors.
140 * This is called the first time it is needed, and also called again
141 * every time the configuration is reloaded, because the charset or
142 * codepage might have changed.
144 void init_iconv(void)
147 bool did_reload
= False
;
149 /* so that charset_name() works we need to get the UNIX<->UCS2 going
151 if (!conv_handles
[CH_UNIX
][CH_UTF16LE
])
152 conv_handles
[CH_UNIX
][CH_UTF16LE
] = smb_iconv_open(charset_name(CH_UTF16LE
), "ASCII");
154 if (!conv_handles
[CH_UTF16LE
][CH_UNIX
])
155 conv_handles
[CH_UTF16LE
][CH_UNIX
] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE
));
157 for (c1
=0;c1
<NUM_CHARSETS
;c1
++) {
158 for (c2
=0;c2
<NUM_CHARSETS
;c2
++) {
159 const char *n1
= charset_name((charset_t
)c1
);
160 const char *n2
= charset_name((charset_t
)c2
);
161 if (conv_handles
[c1
][c2
] &&
162 strcmp(n1
, conv_handles
[c1
][c2
]->from_name
) == 0 &&
163 strcmp(n2
, conv_handles
[c1
][c2
]->to_name
) == 0)
168 if (conv_handles
[c1
][c2
])
169 smb_iconv_close(conv_handles
[c1
][c2
]);
171 conv_handles
[c1
][c2
] = smb_iconv_open(n2
,n1
);
172 if (conv_handles
[c1
][c2
] == (smb_iconv_t
)-1) {
173 DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
174 charset_name((charset_t
)c1
), charset_name((charset_t
)c2
)));
175 if (c1
!= CH_UTF16LE
&& c1
!= CH_UTF16BE
) {
178 if (c2
!= CH_UTF16LE
&& c2
!= CH_UTF16BE
) {
181 DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
183 conv_handles
[c1
][c2
] = smb_iconv_open(n2
,n1
);
184 if (!conv_handles
[c1
][c2
]) {
185 DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1
, n2
));
186 smb_panic("init_iconv: conv_handle initialization failed");
193 /* XXX: Does this really get called every time the dos
194 * codepage changes? */
195 /* XXX: Is the did_reload test too strict? */
203 * Convert string from one encoding to another, making error checking etc
204 * Slow path version - uses (slow) iconv.
206 * @param src pointer to source string (multibyte or singlebyte)
207 * @param srclen length of the source string in bytes
208 * @param dest pointer to destination string (multibyte or singlebyte)
209 * @param destlen maximal length allowed for string
210 * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
211 * @returns the number of bytes occupied in the destination
213 * Ensure the srclen contains the terminating zero.
217 static size_t convert_string_internal(charset_t from
, charset_t to
,
218 void const *src
, size_t srclen
,
219 void *dest
, size_t destlen
, bool allow_bad_conv
)
223 const char* inbuf
= (const char*)src
;
224 char* outbuf
= (char*)dest
;
225 smb_iconv_t descriptor
;
227 lazy_initialize_conv();
229 descriptor
= conv_handles
[from
][to
];
231 if (srclen
== (size_t)-1) {
232 if (from
== CH_UTF16LE
|| from
== CH_UTF16BE
) {
233 srclen
= (strlen_w((const smb_ucs2_t
*)src
)+1) * 2;
235 srclen
= strlen((const char *)src
)+1;
240 if (descriptor
== (smb_iconv_t
)-1 || descriptor
== (smb_iconv_t
)0) {
242 DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
251 retval
= smb_iconv(descriptor
, &inbuf
, &i_len
, &outbuf
, &o_len
);
252 if(retval
==(size_t)-1) {
253 const char *reason
="unknown error";
256 reason
="Incomplete multibyte sequence";
258 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason
,inbuf
));
263 reason
="No more room";
265 if (from
== CH_UNIX
) {
266 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
267 charset_name(from
), charset_name(to
),
268 (unsigned int)srclen
, (unsigned int)destlen
, (const char *)src
));
270 DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
271 charset_name(from
), charset_name(to
),
272 (unsigned int)srclen
, (unsigned int)destlen
));
277 reason
="Illegal multibyte sequence";
279 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason
,inbuf
));
286 DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason
,inbuf
));
289 /* smb_panic(reason); */
291 return destlen
-o_len
;
296 * Conversion not supported. This is actually an error, but there are so
297 * many misconfigured iconv systems and smb.conf's out there we can't just
298 * fail. Do a very bad conversion instead.... JRA.
302 if (o_len
== 0 || i_len
== 0)
303 return destlen
- o_len
;
305 if (((from
== CH_UTF16LE
)||(from
== CH_UTF16BE
)) &&
306 ((to
!= CH_UTF16LE
)||(to
!= CH_UTF16BE
))) {
307 /* Can't convert from utf16 any endian to multibyte.
308 Replace with the default fail char.
311 return destlen
- o_len
;
313 *outbuf
= lp_failed_convert_char();
322 if (o_len
== 0 || i_len
== 0)
323 return destlen
- o_len
;
325 /* Keep trying with the next char... */
328 } else if (from
!= CH_UTF16LE
&& from
!= CH_UTF16BE
&& to
== CH_UTF16LE
) {
329 /* Can't convert to UTF16LE - just widen by adding the
330 default fail char then zero.
333 return destlen
- o_len
;
335 outbuf
[0] = lp_failed_convert_char();
344 if (o_len
== 0 || i_len
== 0)
345 return destlen
- o_len
;
347 /* Keep trying with the next char... */
350 } else if (from
!= CH_UTF16LE
&& from
!= CH_UTF16BE
&&
351 to
!= CH_UTF16LE
&& to
!= CH_UTF16BE
) {
352 /* Failed multibyte to multibyte. Just copy the default fail char and
354 outbuf
[0] = lp_failed_convert_char();
362 if (o_len
== 0 || i_len
== 0)
363 return destlen
- o_len
;
365 /* Keep trying with the next char... */
369 /* Keep compiler happy.... */
370 return destlen
- o_len
;
376 * Convert string from one encoding to another, making error checking etc
377 * Fast path version - handles ASCII first.
379 * @param src pointer to source string (multibyte or singlebyte)
380 * @param srclen length of the source string in bytes, or -1 for nul terminated.
381 * @param dest pointer to destination string (multibyte or singlebyte)
382 * @param destlen maximal length allowed for string - *NEVER* -1.
383 * @param allow_bad_conv determines if a "best effort" conversion is acceptable (never returns errors)
384 * @returns the number of bytes occupied in the destination
386 * Ensure the srclen contains the terminating zero.
388 * This function has been hand-tuned to provide a fast path.
389 * Don't change unless you really know what you are doing. JRA.
392 size_t convert_string(charset_t from
, charset_t to
,
393 void const *src
, size_t srclen
,
394 void *dest
, size_t destlen
, bool allow_bad_conv
)
397 * NB. We deliberately don't do a strlen here if srclen == -1.
398 * This is very expensive over millions of calls and is taken
399 * care of in the slow path in convert_string_internal. JRA.
403 SMB_ASSERT(destlen
!= (size_t)-1);
409 if (from
!= CH_UTF16LE
&& from
!= CH_UTF16BE
&& to
!= CH_UTF16LE
&& to
!= CH_UTF16BE
) {
410 const unsigned char *p
= (const unsigned char *)src
;
411 unsigned char *q
= (unsigned char *)dest
;
412 size_t slen
= srclen
;
413 size_t dlen
= destlen
;
414 unsigned char lastp
= '\0';
417 /* If all characters are ascii, fast path here. */
418 while (slen
&& dlen
) {
419 if ((lastp
= *p
) <= 0x7f) {
421 if (slen
!= (size_t)-1) {
429 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
432 size_t ret
= convert_string_internal(from
, to
, p
, slen
, q
, dlen
, allow_bad_conv
);
433 if (ret
== (size_t)-1) {
441 /* Even if we fast path we should note if we ran out of room. */
442 if (((slen
!= (size_t)-1) && slen
) ||
443 ((slen
== (size_t)-1) && lastp
)) {
448 } else if (from
== CH_UTF16LE
&& to
!= CH_UTF16LE
) {
449 const unsigned char *p
= (const unsigned char *)src
;
450 unsigned char *q
= (unsigned char *)dest
;
452 size_t slen
= srclen
;
453 size_t dlen
= destlen
;
454 unsigned char lastp
= '\0';
456 /* If all characters are ascii, fast path here. */
457 while (((slen
== (size_t)-1) || (slen
>= 2)) && dlen
) {
458 if (((lastp
= *p
) <= 0x7f) && (p
[1] == 0)) {
460 if (slen
!= (size_t)-1) {
469 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
472 size_t ret
= convert_string_internal(from
, to
, p
, slen
, q
, dlen
, allow_bad_conv
);
473 if (ret
== (size_t)-1) {
481 /* Even if we fast path we should note if we ran out of room. */
482 if (((slen
!= (size_t)-1) && slen
) ||
483 ((slen
== (size_t)-1) && lastp
)) {
488 } else if (from
!= CH_UTF16LE
&& from
!= CH_UTF16BE
&& to
== CH_UTF16LE
) {
489 const unsigned char *p
= (const unsigned char *)src
;
490 unsigned char *q
= (unsigned char *)dest
;
492 size_t slen
= srclen
;
493 size_t dlen
= destlen
;
494 unsigned char lastp
= '\0';
496 /* If all characters are ascii, fast path here. */
497 while (slen
&& (dlen
>= 2)) {
498 if ((lastp
= *p
) <= 0x7F) {
501 if (slen
!= (size_t)-1) {
509 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
512 size_t ret
= convert_string_internal(from
, to
, p
, slen
, q
, dlen
, allow_bad_conv
);
513 if (ret
== (size_t)-1) {
521 /* Even if we fast path we should note if we ran out of room. */
522 if (((slen
!= (size_t)-1) && slen
) ||
523 ((slen
== (size_t)-1) && lastp
)) {
530 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
533 return convert_string_internal(from
, to
, src
, srclen
, dest
, destlen
, allow_bad_conv
);
537 * Convert between character sets, allocating a new buffer using talloc for the result.
539 * @param srclen length of source buffer.
540 * @param dest always set at least to NULL
541 * @parm converted_size set to the number of bytes occupied by the string in
542 * the destination on success.
543 * @note -1 is not accepted for srclen.
545 * @return true if new buffer was correctly allocated, and string was
548 * Ensure the srclen contains the terminating zero.
550 * I hate the goto's in this function. It's embarressing.....
551 * There has to be a cleaner way to do this. JRA.
553 bool convert_string_talloc(TALLOC_CTX
*ctx
, charset_t from
, charset_t to
,
554 void const *src
, size_t srclen
, void *dst
,
555 size_t *converted_size
, bool allow_bad_conv
)
558 size_t i_len
, o_len
, destlen
= (srclen
* 3) / 2;
560 const char *inbuf
= (const char *)src
;
561 char *outbuf
= NULL
, *ob
= NULL
;
562 smb_iconv_t descriptor
;
563 void **dest
= (void **)dst
;
567 if (!converted_size
) {
572 if (src
== NULL
|| srclen
== (size_t)-1) {
578 /* We really should treat this as an error, but
579 there are too many callers that need this to
580 return a NULL terminated string in the correct
582 if (to
== CH_UTF16LE
|| to
== CH_UTF16BE
|| to
== CH_UTF16MUNGED
) {
587 ob
= talloc_zero_array(ctx
, char, destlen
);
592 *converted_size
= destlen
;
597 lazy_initialize_conv();
599 descriptor
= conv_handles
[from
][to
];
601 if (descriptor
== (smb_iconv_t
)-1 || descriptor
== (smb_iconv_t
)0) {
603 DEBUG(0,("convert_string_talloc: Conversion not supported.\n"));
610 /* +2 is for ucs2 null termination. */
611 if ((destlen
*2)+2 < destlen
) {
612 /* wrapped ! abort. */
614 DEBUG(0, ("convert_string_talloc: destlen wrapped !\n"));
619 destlen
= destlen
* 2;
622 /* +2 is for ucs2 null termination. */
623 ob
= (char *)TALLOC_REALLOC(ctx
, ob
, destlen
+ 2);
626 DEBUG(0, ("convert_string_talloc: realloc failed!\n"));
636 retval
= smb_iconv(descriptor
,
639 if(retval
== (size_t)-1) {
640 const char *reason
="unknown error";
643 reason
="Incomplete multibyte sequence";
645 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason
,inbuf
));
652 reason
="Illegal multibyte sequence";
654 DEBUG(3,("convert_string_talloc: Conversion error: %s(%s)\n",reason
,inbuf
));
660 DEBUG(0,("Conversion error: %s(%s)\n",reason
,inbuf
));
661 /* smb_panic(reason); */
668 destlen
= destlen
- o_len
;
669 /* Don't shrink unless we're reclaiming a lot of
670 * space. This is in the hot codepath and these
671 * reallocs *cost*. JRA.
674 /* We're shrinking here so we know the +2 is safe from wrap. */
675 ob
= (char *)TALLOC_REALLOC(ctx
,ob
,destlen
+ 2);
678 if (destlen
&& !ob
) {
679 DEBUG(0, ("convert_string_talloc: out of memory!\n"));
686 /* Must ucs2 null terminate in the extra space we allocated. */
688 ob
[destlen
+1] = '\0';
690 /* Ensure we can never return a *converted_size of zero. */
692 /* This can happen from a bad iconv "use_as_is:" call. */
693 if (to
== CH_UTF16LE
|| to
== CH_UTF16BE
|| to
== CH_UTF16MUNGED
) {
700 *converted_size
= destlen
;
706 * Conversion not supported. This is actually an error, but there are so
707 * many misconfigured iconv systems and smb.conf's out there we can't just
708 * fail. Do a very bad conversion instead.... JRA.
712 if (o_len
== 0 || i_len
== 0)
715 if (((from
== CH_UTF16LE
)||(from
== CH_UTF16BE
)) &&
716 ((to
!= CH_UTF16LE
)||(to
!= CH_UTF16BE
))) {
717 /* Can't convert from utf16 any endian to multibyte.
718 Replace with the default fail char.
725 *outbuf
= lp_failed_convert_char();
734 if (o_len
== 0 || i_len
== 0)
737 /* Keep trying with the next char... */
740 } else if (from
!= CH_UTF16LE
&& from
!= CH_UTF16BE
&& to
== CH_UTF16LE
) {
741 /* Can't convert to UTF16LE - just widen by adding the
742 default fail char then zero.
747 outbuf
[0] = lp_failed_convert_char();
756 if (o_len
== 0 || i_len
== 0)
759 /* Keep trying with the next char... */
762 } else if (from
!= CH_UTF16LE
&& from
!= CH_UTF16BE
&&
763 to
!= CH_UTF16LE
&& to
!= CH_UTF16BE
) {
764 /* Failed multibyte to multibyte. Just copy the default fail char and
766 outbuf
[0] = lp_failed_convert_char();
774 if (o_len
== 0 || i_len
== 0)
777 /* Keep trying with the next char... */
781 /* Keep compiler happy.... */
787 size_t unix_strupper(const char *src
, size_t srclen
, char *dest
, size_t destlen
)
792 if (!push_ucs2_talloc(talloc_tos(), &buffer
, src
, &size
)) {
796 if (!strupper_w(buffer
) && (dest
== src
)) {
801 size
= convert_string(CH_UTF16LE
, CH_UNIX
, buffer
, size
, dest
, destlen
, True
);
807 talloc_strdup() a unix string to upper case.
810 char *talloc_strdup_upper(TALLOC_CTX
*ctx
, const char *s
)
812 char *out_buffer
= talloc_strdup(ctx
,s
);
813 const unsigned char *p
= (const unsigned char *)s
;
814 unsigned char *q
= (unsigned char *)out_buffer
;
820 /* this is quite a common operation, so we want it to be
821 fast. We optimise for the ascii case, knowing that all our
822 supported multi-byte character sets are ascii-compatible
823 (ie. they match for the first 128 chars) */
828 *q
++ = toupper_ascii_fast(*p
);
834 size_t converted_size
, converted_size2
;
835 smb_ucs2_t
*ubuf
= NULL
;
837 /* We're not using the ascii buffer above. */
838 TALLOC_FREE(out_buffer
);
840 if (!convert_string_talloc(ctx
, CH_UNIX
, CH_UTF16LE
, s
,
841 strlen(s
)+1, (void *)&ubuf
,
842 &converted_size
, True
))
849 if (!convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
, ubuf
,
850 converted_size
, (void *)&out_buffer
,
851 &converted_size2
, True
))
857 /* Don't need the intermediate buffer
866 char *strupper_talloc(TALLOC_CTX
*ctx
, const char *s
) {
867 return talloc_strdup_upper(ctx
, s
);
871 size_t unix_strlower(const char *src
, size_t srclen
, char *dest
, size_t destlen
)
874 smb_ucs2_t
*buffer
= NULL
;
876 if (!convert_string_talloc(talloc_tos(), CH_UNIX
, CH_UTF16LE
, src
, srclen
,
877 (void **)(void *)&buffer
, &size
,
880 smb_panic("failed to create UCS2 buffer");
882 if (!strlower_w(buffer
) && (dest
== src
)) {
886 size
= convert_string(CH_UTF16LE
, CH_UNIX
, buffer
, size
, dest
, destlen
, True
);
892 char *talloc_strdup_lower(TALLOC_CTX
*ctx
, const char *s
)
894 size_t converted_size
;
895 smb_ucs2_t
*buffer
= NULL
;
898 if (!push_ucs2_talloc(ctx
, &buffer
, s
, &converted_size
)) {
904 if (!pull_ucs2_talloc(ctx
, &out_buffer
, buffer
, &converted_size
)) {
914 char *strlower_talloc(TALLOC_CTX
*ctx
, const char *s
) {
915 return talloc_strdup_lower(ctx
, s
);
918 size_t ucs2_align(const void *base_ptr
, const void *p
, int flags
)
920 if (flags
& (STR_NOALIGN
|STR_ASCII
))
922 return PTR_DIFF(p
, base_ptr
) & 1;
927 * Copy a string from a char* unix src to a dos codepage string destination.
929 * @return the number of bytes occupied by the string in the destination.
931 * @param flags can include
933 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
934 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
937 * @param dest_len the maximum length in bytes allowed in the
940 size_t push_ascii(void *dest
, const char *src
, size_t dest_len
, int flags
)
942 size_t src_len
= strlen(src
);
946 /* No longer allow a length of -1. */
947 if (dest_len
== (size_t)-1) {
948 smb_panic("push_ascii - dest_len == -1");
951 if (flags
& STR_UPPER
) {
952 tmpbuf
= SMB_STRDUP(src
);
954 smb_panic("malloc fail");
960 if (flags
& (STR_TERMINATE
| STR_TERMINATE_ASCII
)) {
964 ret
= convert_string(CH_UNIX
, CH_DOS
, src
, src_len
, dest
, dest_len
, True
);
965 if (ret
== (size_t)-1 &&
966 (flags
& (STR_TERMINATE
| STR_TERMINATE_ASCII
))
968 ((char *)dest
)[0] = '\0';
974 size_t push_ascii_fstring(void *dest
, const char *src
)
976 return push_ascii(dest
, src
, sizeof(fstring
), STR_TERMINATE
);
979 /********************************************************************
980 Push an nstring - ensure null terminated. Written by
981 moriyama@miraclelinux.com (MORIYAMA Masayuki).
982 ********************************************************************/
984 size_t push_ascii_nstring(void *dest
, const char *src
)
986 size_t i
, buffer_len
, dest_len
;
990 if (!push_ucs2_talloc(talloc_tos(), &buffer
, src
, &buffer_len
)) {
991 smb_panic("failed to create UCS2 buffer");
994 /* We're using buffer_len below to count ucs2 characters, not bytes. */
995 buffer_len
/= sizeof(smb_ucs2_t
);
998 for (i
= 0; buffer
[i
] != 0 && (i
< buffer_len
); i
++) {
999 unsigned char mb
[10];
1000 /* Convert one smb_ucs2_t character at a time. */
1001 size_t mb_len
= convert_string(CH_UTF16LE
, CH_DOS
, buffer
+i
, sizeof(smb_ucs2_t
), mb
, sizeof(mb
), False
);
1002 if ((mb_len
!= (size_t)-1) && (dest_len
+ mb_len
<= MAX_NETBIOSNAME_LEN
- 1)) {
1003 memcpy((char *)dest
+ dest_len
, mb
, mb_len
);
1010 ((char *)dest
)[dest_len
] = '\0';
1012 conv_silent
= False
;
1013 TALLOC_FREE(buffer
);
1017 /********************************************************************
1018 Push and malloc an ascii string. src and dest null terminated.
1019 ********************************************************************/
1021 bool push_ascii_talloc(TALLOC_CTX
*mem_ctx
, char **dest
, const char *src
, size_t *converted_size
)
1023 size_t src_len
= strlen(src
)+1;
1026 return convert_string_talloc(mem_ctx
, CH_UNIX
, CH_DOS
, src
, src_len
,
1027 (void **)dest
, converted_size
, True
);
1031 * Copy a string from a dos codepage source to a unix char* destination.
1033 * The resulting string in "dest" is always null terminated.
1035 * @param flags can have:
1037 * <dt>STR_TERMINATE</dt>
1038 * <dd>STR_TERMINATE means the string in @p src
1039 * is null terminated, and src_len is ignored.</dd>
1042 * @param src_len is the length of the source area in bytes.
1043 * @returns the number of bytes occupied by the string in @p src.
1045 size_t pull_ascii(char *dest
, const void *src
, size_t dest_len
, size_t src_len
, int flags
)
1049 if (dest_len
== (size_t)-1) {
1050 /* No longer allow dest_len of -1. */
1051 smb_panic("pull_ascii - invalid dest_len of -1");
1054 if (flags
& STR_TERMINATE
) {
1055 if (src_len
== (size_t)-1) {
1056 src_len
= strlen((const char *)src
) + 1;
1058 size_t len
= strnlen((const char *)src
, src_len
);
1065 ret
= convert_string(CH_DOS
, CH_UNIX
, src
, src_len
, dest
, dest_len
, True
);
1066 if (ret
== (size_t)-1) {
1071 if (dest_len
&& ret
) {
1072 /* Did we already process the terminating zero ? */
1073 if (dest
[MIN(ret
-1, dest_len
-1)] != 0) {
1074 dest
[MIN(ret
, dest_len
-1)] = 0;
1084 * Copy a string from a dos codepage source to a unix char* destination.
1087 * The resulting string in "dest" is always null terminated.
1089 * @param flags can have:
1091 * <dt>STR_TERMINATE</dt>
1092 * <dd>STR_TERMINATE means the string in @p src
1093 * is null terminated, and src_len is ignored.</dd>
1096 * @param src_len is the length of the source area in bytes.
1097 * @returns the number of bytes occupied by the string in @p src.
1100 static size_t pull_ascii_base_talloc(TALLOC_CTX
*ctx
,
1115 if (flags
& STR_TERMINATE
) {
1116 if (src_len
== (size_t)-1) {
1117 src_len
= strlen((const char *)src
) + 1;
1119 size_t len
= strnlen((const char *)src
, src_len
);
1124 /* Ensure we don't use an insane length from the client. */
1125 if (src_len
>= 1024*1024) {
1126 char *msg
= talloc_asprintf(ctx
,
1127 "Bad src length (%u) in "
1128 "pull_ascii_base_talloc",
1129 (unsigned int)src_len
);
1133 /* Can't have an unlimited length
1134 * non STR_TERMINATE'd.
1136 if (src_len
== (size_t)-1) {
1142 /* src_len != -1 here. */
1144 if (!convert_string_talloc(ctx
, CH_DOS
, CH_UNIX
, src
, src_len
, &dest
,
1149 if (dest_len
&& dest
) {
1150 /* Did we already process the terminating zero ? */
1151 if (dest
[dest_len
-1] != 0) {
1152 size_t size
= talloc_get_size(dest
);
1153 /* Have we got space to append the '\0' ? */
1154 if (size
<= dest_len
) {
1156 dest
= TALLOC_REALLOC_ARRAY(ctx
, dest
, char,
1160 dest_len
= (size_t)-1;
1165 dest
[dest_len
] = '\0';
1176 size_t pull_ascii_fstring(char *dest
, const void *src
)
1178 return pull_ascii(dest
, src
, sizeof(fstring
), -1, STR_TERMINATE
);
1181 /* When pulling an nstring it can expand into a larger size (dos cp -> utf8). Cope with this. */
1183 size_t pull_ascii_nstring(char *dest
, size_t dest_len
, const void *src
)
1185 return pull_ascii(dest
, src
, dest_len
, sizeof(nstring
)-1, STR_TERMINATE
);
1189 * Copy a string from a char* src to a unicode destination.
1191 * @returns the number of bytes occupied by the string in the destination.
1193 * @param flags can have:
1196 * <dt>STR_TERMINATE <dd>means include the null termination.
1197 * <dt>STR_UPPER <dd>means uppercase in the destination.
1198 * <dt>STR_NOALIGN <dd>means don't do alignment.
1201 * @param dest_len is the maximum length allowed in the
1205 size_t push_ucs2(const void *base_ptr
, void *dest
, const char *src
, size_t dest_len
, int flags
)
1211 if (dest_len
== (size_t)-1) {
1212 /* No longer allow dest_len of -1. */
1213 smb_panic("push_ucs2 - invalid dest_len of -1");
1216 if (flags
& STR_TERMINATE
)
1217 src_len
= (size_t)-1;
1219 src_len
= strlen(src
);
1221 if (ucs2_align(base_ptr
, dest
, flags
)) {
1223 dest
= (void *)((char *)dest
+ 1);
1229 /* ucs2 is always a multiple of 2 bytes */
1232 ret
= convert_string(CH_UNIX
, CH_UTF16LE
, src
, src_len
, dest
, dest_len
, True
);
1233 if (ret
== (size_t)-1) {
1234 if ((flags
& STR_TERMINATE
) &&
1244 if (flags
& STR_UPPER
) {
1245 smb_ucs2_t
*dest_ucs2
= (smb_ucs2_t
*)dest
;
1248 /* We check for i < (ret / 2) below as the dest string isn't null
1249 terminated if STR_TERMINATE isn't set. */
1251 for (i
= 0; i
< (ret
/ 2) && i
< (dest_len
/ 2) && dest_ucs2
[i
]; i
++) {
1252 smb_ucs2_t v
= toupper_w(dest_ucs2
[i
]);
1253 if (v
!= dest_ucs2
[i
]) {
1264 * Copy a string from a unix char* src to a UCS2 destination,
1265 * allocating a buffer using talloc().
1267 * @param dest always set at least to NULL
1268 * @parm converted_size set to the number of bytes occupied by the string in
1269 * the destination on success.
1271 * @return true if new buffer was correctly allocated, and string was
1274 bool push_ucs2_talloc(TALLOC_CTX
*ctx
, smb_ucs2_t
**dest
, const char *src
,
1275 size_t *converted_size
)
1277 size_t src_len
= strlen(src
)+1;
1280 return convert_string_talloc(ctx
, CH_UNIX
, CH_UTF16LE
, src
, src_len
,
1281 (void **)dest
, converted_size
, True
);
1286 Copy a string from a char* src to a UTF-8 destination.
1287 Return the number of bytes occupied by the string in the destination
1289 STR_TERMINATE means include the null termination
1290 STR_UPPER means uppercase in the destination
1291 dest_len is the maximum length allowed in the destination. If dest_len
1292 is -1 then no maxiumum is used.
1295 static size_t push_utf8(void *dest
, const char *src
, size_t dest_len
, int flags
)
1299 char *tmpbuf
= NULL
;
1301 if (dest_len
== (size_t)-1) {
1302 /* No longer allow dest_len of -1. */
1303 smb_panic("push_utf8 - invalid dest_len of -1");
1306 if (flags
& STR_UPPER
) {
1307 tmpbuf
= strupper_talloc(talloc_tos(), src
);
1312 src_len
= strlen(src
);
1315 src_len
= strlen(src
);
1316 if (flags
& STR_TERMINATE
) {
1320 ret
= convert_string(CH_UNIX
, CH_UTF8
, src
, src_len
, dest
, dest_len
, True
);
1321 TALLOC_FREE(tmpbuf
);
1325 size_t push_utf8_fstring(void *dest
, const char *src
)
1327 return push_utf8(dest
, src
, sizeof(fstring
), STR_TERMINATE
);
1331 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
1333 * @param dest always set at least to NULL
1334 * @parm converted_size set to the number of bytes occupied by the string in
1335 * the destination on success.
1337 * @return true if new buffer was correctly allocated, and string was
1341 bool push_utf8_talloc(TALLOC_CTX
*ctx
, char **dest
, const char *src
,
1342 size_t *converted_size
)
1344 size_t src_len
= strlen(src
)+1;
1347 return convert_string_talloc(ctx
, CH_UNIX
, CH_UTF8
, src
, src_len
,
1348 (void**)dest
, converted_size
, True
);
1352 Copy a string from a ucs2 source to a unix char* destination.
1354 STR_TERMINATE means the string in src is null terminated.
1355 STR_NOALIGN means don't try to align.
1356 if STR_TERMINATE is set then src_len is ignored if it is -1.
1357 src_len is the length of the source area in bytes
1358 Return the number of bytes occupied by the string in src.
1359 The resulting string in "dest" is always null terminated.
1362 size_t pull_ucs2(const void *base_ptr
, char *dest
, const void *src
, size_t dest_len
, size_t src_len
, int flags
)
1365 size_t ucs2_align_len
= 0;
1367 if (dest_len
== (size_t)-1) {
1368 /* No longer allow dest_len of -1. */
1369 smb_panic("pull_ucs2 - invalid dest_len of -1");
1373 if (dest
&& dest_len
> 0) {
1379 if (ucs2_align(base_ptr
, src
, flags
)) {
1380 src
= (const void *)((const char *)src
+ 1);
1381 if (src_len
!= (size_t)-1)
1386 if (flags
& STR_TERMINATE
) {
1387 /* src_len -1 is the default for null terminated strings. */
1388 if (src_len
!= (size_t)-1) {
1389 size_t len
= strnlen_w((const smb_ucs2_t
*)src
,
1391 if (len
< src_len
/2)
1397 /* ucs2 is always a multiple of 2 bytes */
1398 if (src_len
!= (size_t)-1)
1401 ret
= convert_string(CH_UTF16LE
, CH_UNIX
, src
, src_len
, dest
, dest_len
, True
);
1402 if (ret
== (size_t)-1) {
1407 if (src_len
== (size_t)-1)
1410 if (dest_len
&& ret
) {
1411 /* Did we already process the terminating zero ? */
1412 if (dest
[MIN(ret
-1, dest_len
-1)] != 0) {
1413 dest
[MIN(ret
, dest_len
-1)] = 0;
1419 return src_len
+ ucs2_align_len
;
1423 Copy a string from a ucs2 source to a unix char* destination.
1424 Talloc version with a base pointer.
1425 Uses malloc if TALLOC_CTX is NULL (this is a bad interface and
1428 STR_TERMINATE means the string in src is null terminated.
1429 STR_NOALIGN means don't try to align.
1430 if STR_TERMINATE is set then src_len is ignored if it is -1.
1431 src_len is the length of the source area in bytes
1432 Return the number of bytes occupied by the string in src.
1433 The resulting string in "dest" is always null terminated.
1436 size_t pull_ucs2_base_talloc(TALLOC_CTX
*ctx
,
1437 const void *base_ptr
,
1445 size_t ucs2_align_len
= 0;
1450 /* Ensure we never use the braindead "malloc" varient. */
1452 smb_panic("NULL talloc CTX in pull_ucs2_base_talloc\n");
1460 if (ucs2_align(base_ptr
, src
, flags
)) {
1461 src
= (const void *)((const char *)src
+ 1);
1462 if (src_len
!= (size_t)-1)
1467 if (flags
& STR_TERMINATE
) {
1468 /* src_len -1 is the default for null terminated strings. */
1469 if (src_len
!= (size_t)-1) {
1470 size_t len
= strnlen_w((const smb_ucs2_t
*)src
,
1472 if (len
< src_len
/2)
1477 * src_len == -1 - alloc interface won't take this
1478 * so we must calculate.
1480 src_len
= (strlen_w((const smb_ucs2_t
*)src
)+1)*sizeof(smb_ucs2_t
);
1482 /* Ensure we don't use an insane length from the client. */
1483 if (src_len
>= 1024*1024) {
1484 smb_panic("Bad src length in pull_ucs2_base_talloc\n");
1487 /* Can't have an unlimited length
1488 * non STR_TERMINATE'd.
1490 if (src_len
== (size_t)-1) {
1496 /* src_len != -1 here. */
1498 /* ucs2 is always a multiple of 2 bytes */
1501 if (!convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
, src
, src_len
,
1502 (void *)&dest
, &dest_len
, True
)) {
1507 /* Did we already process the terminating zero ? */
1508 if (dest
[dest_len
-1] != 0) {
1509 size_t size
= talloc_get_size(dest
);
1510 /* Have we got space to append the '\0' ? */
1511 if (size
<= dest_len
) {
1513 dest
= TALLOC_REALLOC_ARRAY(ctx
, dest
, char,
1517 dest_len
= (size_t)-1;
1522 dest
[dest_len
] = '\0';
1530 return src_len
+ ucs2_align_len
;
1533 size_t pull_ucs2_fstring(char *dest
, const void *src
)
1535 return pull_ucs2(NULL
, dest
, src
, sizeof(fstring
), -1, STR_TERMINATE
);
1539 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
1541 * @param dest always set at least to NULL
1542 * @parm converted_size set to the number of bytes occupied by the string in
1543 * the destination on success.
1545 * @return true if new buffer was correctly allocated, and string was
1549 bool pull_ucs2_talloc(TALLOC_CTX
*ctx
, char **dest
, const smb_ucs2_t
*src
,
1550 size_t *converted_size
)
1552 size_t src_len
= (strlen_w(src
)+1) * sizeof(smb_ucs2_t
);
1555 return convert_string_talloc(ctx
, CH_UTF16LE
, CH_UNIX
, src
, src_len
,
1556 (void **)dest
, converted_size
, True
);
1560 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
1562 * @param dest always set at least to NULL
1563 * @parm converted_size set to the number of bytes occupied by the string in
1564 * the destination on success.
1566 * @return true if new buffer was correctly allocated, and string was
1570 bool pull_utf8_talloc(TALLOC_CTX
*ctx
, char **dest
, const char *src
,
1571 size_t *converted_size
)
1573 size_t src_len
= strlen(src
)+1;
1576 return convert_string_talloc(ctx
, CH_UTF8
, CH_UNIX
, src
, src_len
,
1577 (void **)dest
, converted_size
, True
);
1582 * Copy a string from a DOS src to a unix char * destination, allocating a buffer using talloc
1584 * @param dest always set at least to NULL
1585 * @parm converted_size set to the number of bytes occupied by the string in
1586 * the destination on success.
1588 * @return true if new buffer was correctly allocated, and string was
1592 bool pull_ascii_talloc(TALLOC_CTX
*ctx
, char **dest
, const char *src
,
1593 size_t *converted_size
)
1595 size_t src_len
= strlen(src
)+1;
1598 return convert_string_talloc(ctx
, CH_DOS
, CH_UNIX
, src
, src_len
,
1599 (void **)dest
, converted_size
, True
);
1603 Copy a string from a char* src to a unicode or ascii
1604 dos codepage destination choosing unicode or ascii based on the
1606 Return the number of bytes occupied by the string in the destination.
1608 STR_TERMINATE means include the null termination.
1609 STR_UPPER means uppercase in the destination.
1610 STR_ASCII use ascii even with unicode packet.
1611 STR_NOALIGN means don't do alignment.
1612 dest_len is the maximum length allowed in the destination. If dest_len
1613 is -1 then no maxiumum is used.
1616 size_t push_string_check_fn(const char *function
, unsigned int line
,
1617 void *dest
, const char *src
,
1618 size_t dest_len
, int flags
)
1621 /* We really need to zero fill here, not clobber
1622 * region, as we want to ensure that valgrind thinks
1623 * all of the outgoing buffer has been written to
1624 * so a send() or write() won't trap an error.
1628 clobber_region(function
, line
, dest
, dest_len
);
1630 memset(dest
, '\0', dest_len
);
1634 if (!(flags
& STR_ASCII
) && (flags
& STR_UNICODE
)) {
1635 return push_ucs2(NULL
, dest
, src
, dest_len
, flags
);
1637 return push_ascii(dest
, src
, dest_len
, flags
);
1642 Copy a string from a char* src to a unicode or ascii
1643 dos codepage destination choosing unicode or ascii based on the
1644 flags in the SMB buffer starting at base_ptr.
1645 Return the number of bytes occupied by the string in the destination.
1647 STR_TERMINATE means include the null termination.
1648 STR_UPPER means uppercase in the destination.
1649 STR_ASCII use ascii even with unicode packet.
1650 STR_NOALIGN means don't do alignment.
1651 dest_len is the maximum length allowed in the destination. If dest_len
1652 is -1 then no maxiumum is used.
1655 size_t push_string_base(const char *function
, unsigned int line
,
1656 const char *base
, uint16 flags2
,
1657 void *dest
, const char *src
,
1658 size_t dest_len
, int flags
)
1661 /* We really need to zero fill here, not clobber
1662 * region, as we want to ensure that valgrind thinks
1663 * all of the outgoing buffer has been written to
1664 * so a send() or write() won't trap an error.
1668 clobber_region(function
, line
, dest
, dest_len
);
1670 memset(dest
, '\0', dest_len
);
1674 if (!(flags
& STR_ASCII
) && \
1675 ((flags
& STR_UNICODE
|| \
1676 (flags2
& FLAGS2_UNICODE_STRINGS
)))) {
1677 return push_ucs2(base
, dest
, src
, dest_len
, flags
);
1679 return push_ascii(dest
, src
, dest_len
, flags
);
1683 Copy a string from a char* src to a unicode or ascii
1684 dos codepage destination choosing unicode or ascii based on the
1686 Return the number of bytes occupied by the string in the destination.
1688 STR_TERMINATE means include the null termination.
1689 STR_UPPER means uppercase in the destination.
1690 STR_ASCII use ascii even with unicode packet.
1691 STR_NOALIGN means don't do alignment.
1692 dest_len is the maximum length allowed in the destination. If dest_len
1693 is -1 then no maxiumum is used.
1696 ssize_t
push_string(void *dest
, const char *src
, size_t dest_len
, int flags
)
1700 /* We really need to zero fill here, not clobber
1701 * region, as we want to ensure that valgrind thinks
1702 * all of the outgoing buffer has been written to
1703 * so a send() or write() won't trap an error.
1706 memset(dest
, '\0', dest_len
);
1709 if (!(flags
& STR_ASCII
) && \
1710 (flags
& STR_UNICODE
)) {
1711 ret
= push_ucs2(NULL
, dest
, src
, dest_len
, flags
);
1713 ret
= push_ascii(dest
, src
, dest_len
, flags
);
1715 if (ret
== (size_t)-1) {
1722 Copy a string from a unicode or ascii source (depending on
1723 the packet flags) to a char* destination.
1725 STR_TERMINATE means the string in src is null terminated.
1726 STR_UNICODE means to force as unicode.
1727 STR_ASCII use ascii even with unicode packet.
1728 STR_NOALIGN means don't do alignment.
1729 if STR_TERMINATE is set then src_len is ignored is it is -1
1730 src_len is the length of the source area in bytes.
1731 Return the number of bytes occupied by the string in src.
1732 The resulting string in "dest" is always null terminated.
1735 size_t pull_string_fn(const char *function
,
1737 const void *base_ptr
,
1746 clobber_region(function
, line
, dest
, dest_len
);
1749 if ((base_ptr
== NULL
) && ((flags
& (STR_ASCII
|STR_UNICODE
)) == 0)) {
1750 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1754 if (!(flags
& STR_ASCII
) && \
1755 ((flags
& STR_UNICODE
|| \
1756 (smb_flags2
& FLAGS2_UNICODE_STRINGS
)))) {
1757 return pull_ucs2(base_ptr
, dest
, src
, dest_len
, src_len
, flags
);
1759 return pull_ascii(dest
, src
, dest_len
, src_len
, flags
);
1763 Copy a string from a unicode or ascii source (depending on
1764 the packet flags) to a char* destination.
1765 Variant that uses talloc.
1767 STR_TERMINATE means the string in src is null terminated.
1768 STR_UNICODE means to force as unicode.
1769 STR_ASCII use ascii even with unicode packet.
1770 STR_NOALIGN means don't do alignment.
1771 if STR_TERMINATE is set then src_len is ignored is it is -1
1772 src_len is the length of the source area in bytes.
1773 Return the number of bytes occupied by the string in src.
1774 The resulting string in "dest" is always null terminated.
1777 size_t pull_string_talloc_fn(const char *function
,
1780 const void *base_ptr
,
1787 if ((base_ptr
== NULL
) && ((flags
& (STR_ASCII
|STR_UNICODE
)) == 0)) {
1788 smb_panic("No base ptr to get flg2 and neither ASCII nor "
1792 if (!(flags
& STR_ASCII
) && \
1793 ((flags
& STR_UNICODE
|| \
1794 (smb_flags2
& FLAGS2_UNICODE_STRINGS
)))) {
1795 return pull_ucs2_base_talloc(ctx
,
1802 return pull_ascii_base_talloc(ctx
,
1810 size_t align_string(const void *base_ptr
, const char *p
, int flags
)
1812 if (!(flags
& STR_ASCII
) && \
1813 ((flags
& STR_UNICODE
|| \
1814 (SVAL(base_ptr
, smb_flg2
) & FLAGS2_UNICODE_STRINGS
)))) {
1815 return ucs2_align(base_ptr
, p
, flags
);
1821 Return the unicode codepoint for the next multi-byte CH_UNIX character
1822 in the string. The unicode codepoint (codepoint_t) is an unsinged 32 bit value.
1824 Also return the number of bytes consumed (which tells the caller
1825 how many bytes to skip to get to the next CH_UNIX character).
1827 Return INVALID_CODEPOINT if the next character cannot be converted.
1830 codepoint_t
next_codepoint(const char *str
, size_t *size
)
1832 /* It cannot occupy more than 4 bytes in UTF16 format */
1834 smb_iconv_t descriptor
;
1840 if ((str
[0] & 0x80) == 0) {
1842 return (codepoint_t
)str
[0];
1845 /* We assume that no multi-byte character can take
1846 more than 5 bytes. This is OK as we only
1847 support codepoints up to 1M */
1849 ilen_orig
= strnlen(str
, 5);
1852 lazy_initialize_conv();
1854 descriptor
= conv_handles
[CH_UNIX
][CH_UTF16LE
];
1855 if (descriptor
== (smb_iconv_t
)-1 || descriptor
== (smb_iconv_t
)0) {
1857 return INVALID_CODEPOINT
;
1860 /* This looks a little strange, but it is needed to cope
1861 with codepoints above 64k which are encoded as per RFC2781. */
1863 outbuf
= (char *)buf
;
1864 smb_iconv(descriptor
, &str
, &ilen
, &outbuf
, &olen
);
1866 /* We failed to convert to a 2 byte character.
1867 See if we can convert to a 4 UTF16-LE byte char encoding.
1870 outbuf
= (char *)buf
;
1871 smb_iconv(descriptor
, &str
, &ilen
, &outbuf
, &olen
);
1873 /* We didn't convert any bytes */
1875 return INVALID_CODEPOINT
;
1882 *size
= ilen_orig
- ilen
;
1885 /* 2 byte, UTF16-LE encoded value. */
1886 return (codepoint_t
)SVAL(buf
, 0);
1889 /* Decode a 4 byte UTF16-LE character manually.
1890 See RFC2871 for the encoding machanism.
1892 codepoint_t w1
= SVAL(buf
,0) & ~0xD800;
1893 codepoint_t w2
= SVAL(buf
,2) & ~0xDC00;
1895 return (codepoint_t
)0x10000 +
1899 /* no other length is valid */
1900 return INVALID_CODEPOINT
;
1904 push a single codepoint into a CH_UNIX string the target string must
1905 be able to hold the full character, which is guaranteed if it is at
1906 least 5 bytes in size. The caller may pass less than 5 bytes if they
1907 are sure the character will fit (for example, you can assume that
1908 uppercase/lowercase of a character will not add more than 1 byte)
1910 return the number of bytes occupied by the CH_UNIX character, or
1913 _PUBLIC_ ssize_t
push_codepoint(char *str
, codepoint_t c
)
1915 smb_iconv_t descriptor
;
1925 lazy_initialize_conv();
1927 descriptor
= conv_handles
[CH_UNIX
][CH_UTF16LE
];
1928 if (descriptor
== (smb_iconv_t
)-1 || descriptor
== (smb_iconv_t
)0) {
1935 inbuf
= (char *)buf
;
1937 smb_iconv(descriptor
, &inbuf
, &ilen
, &str
, &olen
);
1946 buf
[0] = (c
>>10) & 0xFF;
1947 buf
[1] = (c
>>18) | 0xd8;
1949 buf
[3] = ((c
>>8) & 0x3) | 0xdc;
1953 inbuf
= (char *)buf
;
1955 smb_iconv(descriptor
, &inbuf
, &ilen
, &str
, &olen
);