* add a few useful debug lines
[Samba/gebeck_regimport.git] / source / lib / charcnv.c
blob6a004021939dbcf411a4052b3ce73e8bba131f15
1 /*
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 2 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, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 /**
27 * @file
29 * @brief Character-set conversion routines built on our iconv.
31 * @note Samba's internal character set (at least in the 3.0 series)
32 * is always the same as the one for the Unix filesystem. It is
33 * <b>not</b> necessarily UTF-8 and may be different on machines that
34 * need i18n filenames to be compatible with Unix software. It does
35 * have to be a superset of ASCII. All multibyte sequences must start
36 * with a byte with the high bit set.
38 * @sa lib/iconv.c
42 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
43 static BOOL conv_silent; /* Should we do a debug if the conversion fails ? */
45 /**
46 * Return the name of a charset to give to iconv().
47 **/
48 static const char *charset_name(charset_t ch)
50 const char *ret = NULL;
52 if (ch == CH_UCS2) ret = "UCS-2LE";
53 else if (ch == CH_UNIX) ret = lp_unix_charset();
54 else if (ch == CH_DOS) ret = lp_dos_charset();
55 else if (ch == CH_DISPLAY) ret = lp_display_charset();
56 else if (ch == CH_UTF8) ret = "UTF8";
58 #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
59 if (ret && !strcmp(ret, "LOCALE")) {
60 const char *ln = NULL;
62 #ifdef HAVE_SETLOCALE
63 setlocale(LC_ALL, "");
64 #endif
65 ln = nl_langinfo(CODESET);
66 if (ln) {
67 /* Check whether the charset name is supported
68 by iconv */
69 smb_iconv_t handle = smb_iconv_open(ln,"UCS-2LE");
70 if (handle == (smb_iconv_t) -1) {
71 DEBUG(5,("Locale charset '%s' unsupported, using ASCII instead\n", ln));
72 ln = NULL;
73 } else {
74 DEBUG(5,("Substituting charset '%s' for LOCALE\n", ln));
75 smb_iconv_close(handle);
78 ret = ln;
80 #endif
82 if (!ret || !*ret) ret = "ASCII";
83 return ret;
86 void lazy_initialize_conv(void)
88 static int initialized = False;
90 if (!initialized) {
91 initialized = True;
92 load_case_tables();
93 init_iconv();
97 /**
98 * Initialize iconv conversion descriptors.
100 * This is called the first time it is needed, and also called again
101 * every time the configuration is reloaded, because the charset or
102 * codepage might have changed.
104 void init_iconv(void)
106 int c1, c2;
107 BOOL did_reload = False;
109 /* so that charset_name() works we need to get the UNIX<->UCS2 going
110 first */
111 if (!conv_handles[CH_UNIX][CH_UCS2])
112 conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
114 if (!conv_handles[CH_UCS2][CH_UNIX])
115 conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
117 for (c1=0;c1<NUM_CHARSETS;c1++) {
118 for (c2=0;c2<NUM_CHARSETS;c2++) {
119 const char *n1 = charset_name((charset_t)c1);
120 const char *n2 = charset_name((charset_t)c2);
121 if (conv_handles[c1][c2] &&
122 strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
123 strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
124 continue;
126 did_reload = True;
128 if (conv_handles[c1][c2])
129 smb_iconv_close(conv_handles[c1][c2]);
131 conv_handles[c1][c2] = smb_iconv_open(n2,n1);
132 if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
133 DEBUG(0,("Conversion from %s to %s not supported\n",
134 charset_name((charset_t)c1), charset_name((charset_t)c2)));
135 conv_handles[c1][c2] = NULL;
140 if (did_reload) {
141 /* XXX: Does this really get called every time the dos
142 * codepage changes? */
143 /* XXX: Is the did_reload test too strict? */
144 conv_silent = True;
145 init_doschar_table();
146 init_valid_table();
147 conv_silent = False;
152 * Convert string from one encoding to another, making error checking etc
153 * Slow path version - uses (slow) iconv.
155 * @param src pointer to source string (multibyte or singlebyte)
156 * @param srclen length of the source string in bytes
157 * @param dest pointer to destination string (multibyte or singlebyte)
158 * @param destlen maximal length allowed for string
159 * @returns the number of bytes occupied in the destination
161 * Ensure the srclen contains the terminating zero.
165 static size_t convert_string_internal(charset_t from, charset_t to,
166 void const *src, size_t srclen,
167 void *dest, size_t destlen)
169 size_t i_len, o_len;
170 size_t retval;
171 const char* inbuf = (const char*)src;
172 char* outbuf = (char*)dest;
173 smb_iconv_t descriptor;
175 lazy_initialize_conv();
177 descriptor = conv_handles[from][to];
179 if (srclen == (size_t)-1) {
180 if (from == CH_UCS2) {
181 srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
182 } else {
183 srclen = strlen((const char *)src)+1;
187 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
188 if (!conv_silent)
189 DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
190 goto use_as_is;
193 i_len=srclen;
194 o_len=destlen;
195 retval = smb_iconv(descriptor, (char **)&inbuf, &i_len, &outbuf, &o_len);
196 if(retval==(size_t)-1) {
197 const char *reason="unknown error";
198 switch(errno) {
199 case EINVAL:
200 reason="Incomplete multibyte sequence";
201 if (!conv_silent)
202 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
203 goto use_as_is;
204 case E2BIG:
205 reason="No more room";
206 if (!conv_silent)
207 DEBUG(3, ("convert_string_internal: Required %lu, available %lu\n",
208 (unsigned long)srclen, (unsigned long)destlen));
209 /* we are not sure we need srclen bytes,
210 may be more, may be less.
211 We only know we need more than destlen
212 bytes ---simo */
213 break;
214 case EILSEQ:
215 reason="Illegal multibyte sequence";
216 if (!conv_silent)
217 DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
218 goto use_as_is;
219 default:
220 if (!conv_silent)
221 DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
222 break;
224 /* smb_panic(reason); */
226 return destlen-o_len;
228 use_as_is:
230 /* conversion not supported, use as is */
232 size_t len = MIN(srclen,destlen);
233 if (len)
234 memcpy(dest,src,len);
235 return len;
240 * Convert string from one encoding to another, making error checking etc
241 * Fast path version - handles ASCII first.
243 * @param src pointer to source string (multibyte or singlebyte)
244 * @param srclen length of the source string in bytes
245 * @param dest pointer to destination string (multibyte or singlebyte)
246 * @param destlen maximal length allowed for string
247 * @returns the number of bytes occupied in the destination
249 * Ensure the srclen contains the terminating zero.
251 * This function has been hand-tuned to provide a fast path.
252 * Don't change unless you really know what you are doing. JRA.
255 size_t convert_string(charset_t from, charset_t to,
256 void const *src, size_t srclen,
257 void *dest, size_t destlen)
260 * NB. We deliberately don't do a strlen here is srclen == -1.
261 * This is very expensive over millions of calls and is taken
262 * care of in the slow path in convert_string_internal. JRA.
265 if (srclen == 0)
266 return 0;
268 if (from != CH_UCS2 && to != CH_UCS2) {
269 const unsigned char *p = (const unsigned char *)src;
270 unsigned char *q = (unsigned char *)dest;
271 size_t slen = srclen;
272 size_t dlen = destlen;
273 unsigned char lastp;
274 size_t retval = 0;
276 /* If all characters are ascii, fast path here. */
277 while (slen && dlen) {
278 if ((lastp = *p) <= 0x7f) {
279 *q++ = *p++;
280 if (slen != (size_t)-1) {
281 slen--;
283 dlen--;
284 retval++;
285 if (!lastp)
286 break;
287 } else {
288 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
289 goto general_case;
290 #else
291 return retval + convert_string_internal(from, to, p, slen, q, dlen);
292 #endif
295 return retval;
296 } else if (from == CH_UCS2 && to != CH_UCS2) {
297 const unsigned char *p = (const unsigned char *)src;
298 unsigned char *q = (unsigned char *)dest;
299 size_t retval = 0;
300 size_t slen = srclen;
301 size_t dlen = destlen;
302 unsigned char lastp;
304 /* If all characters are ascii, fast path here. */
305 while ((slen >= 2) && dlen) {
306 if (((lastp = *p) <= 0x7f) && (p[1] == 0)) {
307 *q++ = *p;
308 if (slen != (size_t)-1) {
309 slen -= 2;
311 p += 2;
312 dlen--;
313 retval++;
314 if (!lastp)
315 break;
316 } else {
317 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
318 goto general_case;
319 #else
320 return retval + convert_string_internal(from, to, p, slen, q, dlen);
321 #endif
324 return retval;
325 } else if (from != CH_UCS2 && to == CH_UCS2) {
326 const unsigned char *p = (const unsigned char *)src;
327 unsigned char *q = (unsigned char *)dest;
328 size_t retval = 0;
329 size_t slen = srclen;
330 size_t dlen = destlen;
331 unsigned char lastp;
333 /* If all characters are ascii, fast path here. */
334 while (slen && (dlen >= 2)) {
335 if ((lastp = *p) <= 0x7F) {
336 *q++ = *p++;
337 *q++ = '\0';
338 if (slen != (size_t)-1) {
339 slen--;
341 dlen -= 2;
342 retval += 2;
343 if (!lastp)
344 break;
345 } else {
346 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
347 goto general_case;
348 #else
349 return retval + convert_string_internal(from, to, p, slen, q, dlen);
350 #endif
353 return retval;
356 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
357 general_case:
358 #endif
359 return convert_string_internal(from, to, src, srclen, dest, destlen);
363 * Convert between character sets, allocating a new buffer for the result.
365 * @param ctx TALLOC_CTX to use to allocate with. If NULL use malloc.
366 * @param srclen length of source buffer.
367 * @param dest always set at least to NULL
368 * @note -1 is not accepted for srclen.
370 * @returns Size in bytes of the converted string; or -1 in case of error.
372 * Ensure the srclen contains the terminating zero.
375 size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
376 void const *src, size_t srclen, void **dest)
378 size_t i_len, o_len, destlen = MAX(srclen, 512);
379 size_t retval;
380 const char *inbuf = (const char *)src;
381 char *outbuf = NULL, *ob = NULL;
382 smb_iconv_t descriptor;
384 *dest = NULL;
386 if (src == NULL || srclen == (size_t)-1)
387 return (size_t)-1;
388 if (srclen == 0)
389 return 0;
391 lazy_initialize_conv();
393 descriptor = conv_handles[from][to];
395 if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
396 if (!conv_silent)
397 DEBUG(0,("convert_string_allocate: Conversion not supported.\n"));
398 goto use_as_is;
401 convert:
402 if ((destlen*2) < destlen) {
403 /* wrapped ! abort. */
404 if (!conv_silent)
405 DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
406 if (!ctx)
407 SAFE_FREE(outbuf);
408 return (size_t)-1;
409 } else {
410 destlen = destlen * 2;
413 if (ctx)
414 ob = (char *)talloc_realloc(ctx, ob, destlen);
415 else
416 ob = (char *)Realloc(ob, destlen);
418 if (!ob) {
419 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
420 if (!ctx)
421 SAFE_FREE(outbuf);
422 return (size_t)-1;
423 } else {
424 outbuf = ob;
426 i_len = srclen;
427 o_len = destlen;
428 retval = smb_iconv(descriptor,
429 (char **)&inbuf, &i_len,
430 &outbuf, &o_len);
431 if(retval == (size_t)-1) {
432 const char *reason="unknown error";
433 switch(errno) {
434 case EINVAL:
435 reason="Incomplete multibyte sequence";
436 if (!conv_silent)
437 DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
438 goto use_as_is;
439 case E2BIG:
440 goto convert;
441 case EILSEQ:
442 reason="Illegal multibyte sequence";
443 if (!conv_silent)
444 DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
445 goto use_as_is;
447 if (!conv_silent)
448 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
449 /* smb_panic(reason); */
450 return (size_t)-1;
453 destlen = destlen - o_len;
454 if (ctx)
455 *dest = (char *)talloc_realloc(ctx,ob,destlen);
456 else
457 *dest = (char *)Realloc(ob,destlen);
458 if (destlen && !*dest) {
459 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
460 if (!ctx)
461 SAFE_FREE(ob);
462 return (size_t)-1;
465 return destlen;
467 use_as_is:
469 /* conversion not supported, use as is */
471 if (srclen && (destlen != srclen)) {
472 destlen = srclen;
473 if (ctx)
474 ob = (char *)talloc_realloc(ctx, ob, destlen);
475 else
476 ob = (char *)Realloc(ob, destlen);
477 if (!ob) {
478 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
479 if (!ctx)
480 SAFE_FREE(outbuf);
481 return (size_t)-1;
484 if (srclen && ob)
485 memcpy(ob,(const char *)src,srclen);
486 *dest = (char *)ob;
487 return srclen;
492 * Convert between character sets, allocating a new buffer using talloc for the result.
494 * @param srclen length of source buffer.
495 * @param dest always set at least to NULL
496 * @note -1 is not accepted for srclen.
498 * @returns Size in bytes of the converted string; or -1 in case of error.
500 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
501 void const *src, size_t srclen, void **dest)
503 size_t dest_len;
505 *dest = NULL;
506 dest_len=convert_string_allocate(ctx, from, to, src, srclen, dest);
507 if (dest_len == (size_t)-1)
508 return (size_t)-1;
509 if (*dest == NULL)
510 return (size_t)-1;
511 return dest_len;
514 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
516 size_t size;
517 smb_ucs2_t *buffer;
519 size = push_ucs2_allocate(&buffer, src);
520 if (size == -1) {
521 smb_panic("failed to create UCS2 buffer");
523 if (!strupper_w(buffer) && (dest == src)) {
524 free(buffer);
525 return srclen;
528 size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
529 free(buffer);
530 return size;
534 strdup() a unix string to upper case.
535 Max size is pstring.
538 char *strdup_upper(const char *s)
540 pstring out_buffer;
541 const unsigned char *p = (const unsigned char *)s;
542 unsigned char *q = (unsigned char *)out_buffer;
544 /* this is quite a common operation, so we want it to be
545 fast. We optimise for the ascii case, knowing that all our
546 supported multi-byte character sets are ascii-compatible
547 (ie. they match for the first 128 chars) */
549 while (1) {
550 if (*p & 0x80)
551 break;
552 *q++ = toupper(*p);
553 if (!*p)
554 break;
555 p++;
556 if (p - ( const unsigned char *)s >= sizeof(pstring))
557 break;
560 if (*p) {
561 /* MB case. */
562 size_t size;
563 wpstring buffer;
564 size = convert_string(CH_UNIX, CH_UCS2, s, -1, buffer, sizeof(buffer));
565 if (size == -1) {
566 return NULL;
569 strupper_w(buffer);
571 size = convert_string(CH_UCS2, CH_UNIX, buffer, -1, out_buffer, sizeof(out_buffer));
572 if (size == -1) {
573 return NULL;
577 return strdup(out_buffer);
580 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
582 size_t size;
583 smb_ucs2_t *buffer = NULL;
585 size = convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, srclen,
586 (void **) &buffer);
587 if (size == -1 || !buffer) {
588 smb_panic("failed to create UCS2 buffer");
590 if (!strlower_w(buffer) && (dest == src)) {
591 SAFE_FREE(buffer);
592 return srclen;
594 size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
595 SAFE_FREE(buffer);
596 return size;
600 strdup() a unix string to lower case.
603 char *strdup_lower(const char *s)
605 size_t size;
606 smb_ucs2_t *buffer = NULL;
607 char *out_buffer;
609 size = push_ucs2_allocate(&buffer, s);
610 if (size == -1 || !buffer) {
611 return NULL;
614 strlower_w(buffer);
616 size = pull_ucs2_allocate(&out_buffer, buffer);
617 SAFE_FREE(buffer);
619 if (size == -1) {
620 return NULL;
623 return out_buffer;
626 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
628 if (flags & (STR_NOALIGN|STR_ASCII))
629 return 0;
630 return PTR_DIFF(p, base_ptr) & 1;
635 * Copy a string from a char* unix src to a dos codepage string destination.
637 * @return the number of bytes occupied by the string in the destination.
639 * @param flags can include
640 * <dl>
641 * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
642 * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
643 * </dl>
645 * @param dest_len the maximum length in bytes allowed in the
646 * destination. If @p dest_len is -1 then no maximum is used.
648 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
650 size_t src_len = strlen(src);
651 pstring tmpbuf;
653 /* treat a pstring as "unlimited" length */
654 if (dest_len == (size_t)-1)
655 dest_len = sizeof(pstring);
657 if (flags & STR_UPPER) {
658 pstrcpy(tmpbuf, src);
659 strupper_m(tmpbuf);
660 src = tmpbuf;
663 if (flags & (STR_TERMINATE | STR_TERMINATE_ASCII))
664 src_len++;
666 return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
669 size_t push_ascii_fstring(void *dest, const char *src)
671 return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
674 size_t push_ascii_pstring(void *dest, const char *src)
676 return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
679 size_t push_ascii_nstring(void *dest, const char *src)
681 return push_ascii(dest, src, sizeof(nstring), STR_TERMINATE);
685 * Copy a string from a dos codepage source to a unix char* destination.
687 * The resulting string in "dest" is always null terminated.
689 * @param flags can have:
690 * <dl>
691 * <dt>STR_TERMINATE</dt>
692 * <dd>STR_TERMINATE means the string in @p src
693 * is null terminated, and src_len is ignored.</dd>
694 * </dl>
696 * @param src_len is the length of the source area in bytes.
697 * @returns the number of bytes occupied by the string in @p src.
699 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
701 size_t ret;
703 if (dest_len == (size_t)-1)
704 dest_len = sizeof(pstring);
706 if (flags & STR_TERMINATE) {
707 if (src_len == (size_t)-1) {
708 src_len = strlen(src) + 1;
709 } else {
710 size_t len = strnlen(src, src_len);
711 if (len < src_len)
712 len++;
713 src_len = len;
717 ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
719 if (dest_len)
720 dest[MIN(ret, dest_len-1)] = 0;
721 else
722 dest[0] = 0;
724 return src_len;
727 size_t pull_ascii_pstring(char *dest, const void *src)
729 return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
732 size_t pull_ascii_fstring(char *dest, const void *src)
734 return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
737 size_t pull_ascii_nstring(char *dest, const void *src)
739 return pull_ascii(dest, src, sizeof(nstring), sizeof(nstring), STR_TERMINATE);
743 * Copy a string from a char* src to a unicode destination.
745 * @returns the number of bytes occupied by the string in the destination.
747 * @param flags can have:
749 * <dl>
750 * <dt>STR_TERMINATE <dd>means include the null termination.
751 * <dt>STR_UPPER <dd>means uppercase in the destination.
752 * <dt>STR_NOALIGN <dd>means don't do alignment.
753 * </dl>
755 * @param dest_len is the maximum length allowed in the
756 * destination. If dest_len is -1 then no maxiumum is used.
759 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
761 size_t len=0;
762 size_t src_len;
764 /* treat a pstring as "unlimited" length */
765 if (dest_len == (size_t)-1)
766 dest_len = sizeof(pstring);
768 if (flags & STR_TERMINATE)
769 src_len = (size_t)-1;
770 else
771 src_len = strlen(src);
773 if (ucs2_align(base_ptr, dest, flags)) {
774 *(char *)dest = 0;
775 dest = (void *)((char *)dest + 1);
776 if (dest_len)
777 dest_len--;
778 len++;
781 /* ucs2 is always a multiple of 2 bytes */
782 dest_len &= ~1;
784 len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
786 if (flags & STR_UPPER) {
787 smb_ucs2_t *dest_ucs2 = dest;
788 size_t i;
789 for (i = 0; i < (dest_len / 2) && dest_ucs2[i]; i++) {
790 smb_ucs2_t v = toupper_w(dest_ucs2[i]);
791 if (v != dest_ucs2[i]) {
792 dest_ucs2[i] = v;
797 return len;
802 * Copy a string from a unix char* src to a UCS2 destination,
803 * allocating a buffer using talloc().
805 * @param dest always set at least to NULL
807 * @returns The number of bytes occupied by the string in the destination
808 * or -1 in case of error.
810 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
812 size_t src_len = strlen(src)+1;
814 *dest = NULL;
815 return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
820 * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
822 * @param dest always set at least to NULL
824 * @returns The number of bytes occupied by the string in the destination
825 * or -1 in case of error.
828 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
830 size_t src_len = strlen(src)+1;
832 *dest = NULL;
833 return convert_string_allocate(NULL, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
837 Copy a string from a char* src to a UTF-8 destination.
838 Return the number of bytes occupied by the string in the destination
839 Flags can have:
840 STR_TERMINATE means include the null termination
841 STR_UPPER means uppercase in the destination
842 dest_len is the maximum length allowed in the destination. If dest_len
843 is -1 then no maxiumum is used.
846 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
848 size_t src_len = strlen(src);
849 pstring tmpbuf;
851 /* treat a pstring as "unlimited" length */
852 if (dest_len == (size_t)-1)
853 dest_len = sizeof(pstring);
855 if (flags & STR_UPPER) {
856 pstrcpy(tmpbuf, src);
857 strupper_m(tmpbuf);
858 src = tmpbuf;
861 if (flags & STR_TERMINATE)
862 src_len++;
864 return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
867 size_t push_utf8_fstring(void *dest, const char *src)
869 return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
873 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
875 * @param dest always set at least to NULL
877 * @returns The number of bytes occupied by the string in the destination
880 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
882 size_t src_len = strlen(src)+1;
884 *dest = NULL;
885 return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
889 * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
891 * @param dest always set at least to NULL
893 * @returns The number of bytes occupied by the string in the destination
896 size_t push_utf8_allocate(char **dest, const char *src)
898 size_t src_len = strlen(src)+1;
900 *dest = NULL;
901 return convert_string_allocate(NULL, CH_UNIX, CH_UTF8, src, src_len, (void **)dest);
905 Copy a string from a ucs2 source to a unix char* destination.
906 Flags can have:
907 STR_TERMINATE means the string in src is null terminated.
908 STR_NOALIGN means don't try to align.
909 if STR_TERMINATE is set then src_len is ignored if it is -1.
910 src_len is the length of the source area in bytes
911 Return the number of bytes occupied by the string in src.
912 The resulting string in "dest" is always null terminated.
915 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
917 size_t ret;
919 if (dest_len == (size_t)-1)
920 dest_len = sizeof(pstring);
922 if (ucs2_align(base_ptr, src, flags)) {
923 src = (const void *)((const char *)src + 1);
924 if (src_len > 0)
925 src_len--;
928 if (flags & STR_TERMINATE) {
929 /* src_len -1 is the default for null terminated strings. */
930 if (src_len != (size_t)-1) {
931 size_t len = strnlen_w(src, src_len/2);
932 if (len < src_len/2)
933 len++;
934 src_len = len*2;
938 /* ucs2 is always a multiple of 2 bytes */
939 if (src_len != (size_t)-1)
940 src_len &= ~1;
942 ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
943 if (dest_len)
944 dest[MIN(ret, dest_len-1)] = 0;
945 else
946 dest[0] = 0;
948 return src_len;
951 size_t pull_ucs2_pstring(char *dest, const void *src)
953 return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
956 size_t pull_ucs2_fstring(char *dest, const void *src)
958 return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
962 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
964 * @param dest always set at least to NULL
966 * @returns The number of bytes occupied by the string in the destination
969 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
971 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
972 *dest = NULL;
973 return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
977 * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
979 * @param dest always set at least to NULL
981 * @returns The number of bytes occupied by the string in the destination
984 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
986 size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
987 *dest = NULL;
988 return convert_string_allocate(NULL, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
992 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
994 * @param dest always set at least to NULL
996 * @returns The number of bytes occupied by the string in the destination
999 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
1001 size_t src_len = strlen(src)+1;
1002 *dest = NULL;
1003 return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);
1007 * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
1009 * @param dest always set at least to NULL
1011 * @returns The number of bytes occupied by the string in the destination
1014 size_t pull_utf8_allocate(void **dest, const char *src)
1016 size_t src_len = strlen(src)+1;
1017 *dest = NULL;
1018 return convert_string_allocate(NULL, CH_UTF8, CH_UNIX, src, src_len, dest);
1022 Copy a string from a char* src to a unicode or ascii
1023 dos codepage destination choosing unicode or ascii based on the
1024 flags in the SMB buffer starting at base_ptr.
1025 Return the number of bytes occupied by the string in the destination.
1026 flags can have:
1027 STR_TERMINATE means include the null termination.
1028 STR_UPPER means uppercase in the destination.
1029 STR_ASCII use ascii even with unicode packet.
1030 STR_NOALIGN means don't do alignment.
1031 dest_len is the maximum length allowed in the destination. If dest_len
1032 is -1 then no maxiumum is used.
1035 size_t push_string_fn(const char *function, unsigned int line, const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
1037 #ifdef DEVELOPER
1038 /* We really need to zero fill here, not clobber
1039 * region, as we want to ensure that valgrind thinks
1040 * all of the outgoing buffer has been written to
1041 * so a send() or write() won't trap an error.
1042 * JRA.
1044 #if 0
1045 if (dest_len != (size_t)-1)
1046 clobber_region(function, line, dest, dest_len);
1047 #else
1048 if (dest_len != (size_t)-1)
1049 memset(dest, '\0', dest_len);
1050 #endif
1051 #endif
1053 if (!(flags & STR_ASCII) && \
1054 ((flags & STR_UNICODE || \
1055 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1056 return push_ucs2(base_ptr, dest, src, dest_len, flags);
1058 return push_ascii(dest, src, dest_len, flags);
1063 Copy a string from a unicode or ascii source (depending on
1064 the packet flags) to a char* destination.
1065 Flags can have:
1066 STR_TERMINATE means the string in src is null terminated.
1067 STR_UNICODE means to force as unicode.
1068 STR_ASCII use ascii even with unicode packet.
1069 STR_NOALIGN means don't do alignment.
1070 if STR_TERMINATE is set then src_len is ignored is it is -1
1071 src_len is the length of the source area in bytes.
1072 Return the number of bytes occupied by the string in src.
1073 The resulting string in "dest" is always null terminated.
1076 size_t pull_string_fn(const char *function, unsigned int line, const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
1078 #ifdef DEVELOPER
1079 if (dest_len != (size_t)-1)
1080 clobber_region(function, line, dest, dest_len);
1081 #endif
1083 if (!(flags & STR_ASCII) && \
1084 ((flags & STR_UNICODE || \
1085 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1086 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
1088 return pull_ascii(dest, src, dest_len, src_len, flags);
1091 size_t align_string(const void *base_ptr, const char *p, int flags)
1093 if (!(flags & STR_ASCII) && \
1094 ((flags & STR_UNICODE || \
1095 (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
1096 return ucs2_align(base_ptr, p, flags);
1098 return 0;