This commit was manufactured by cvs2svn to create branch 'SAMBA_3_0'.(This used to...
[ira/wip.git] / source3 / lib / charcnv.c
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
8    
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.
13    
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.
18    
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.
22
23 */
24 #include "includes.h"
25
26 /**
27  * @file
28  *
29  * @brief Character-set conversion routines built on our iconv.
30  * 
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.
37  *
38  * @sa lib/iconv.c
39  */
40
41
42 static smb_iconv_t conv_handles[NUM_CHARSETS][NUM_CHARSETS];
43
44
45 /**
46  * Return the name of a charset to give to iconv().
47  **/
48 static const char *charset_name(charset_t ch)
49 {
50         const char *ret = NULL;
51
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";
57
58         if (!ret || !*ret) ret = "ASCII";
59         return ret;
60 }
61
62 void lazy_initialize_conv(void)
63 {
64         static int initialized = False;
65
66         if (!initialized) {
67                 initialized = True;
68                 load_case_tables();
69                 init_iconv();
70         }
71 }
72
73 /**
74  * Initialize iconv conversion descriptors.
75  *
76  * This is called the first time it is needed, and also called again
77  * every time the configuration is reloaded, because the charset or
78  * codepage might have changed.
79  **/
80 void init_iconv(void)
81 {
82         int c1, c2;
83         BOOL did_reload = False;
84
85         /* so that charset_name() works we need to get the UNIX<->UCS2 going
86            first */
87         if (!conv_handles[CH_UNIX][CH_UCS2])
88                 conv_handles[CH_UNIX][CH_UCS2] = smb_iconv_open("UCS-2LE", "ASCII");
89
90         if (!conv_handles[CH_UCS2][CH_UNIX])
91                 conv_handles[CH_UCS2][CH_UNIX] = smb_iconv_open("ASCII", "UCS-2LE");
92
93         for (c1=0;c1<NUM_CHARSETS;c1++) {
94                 for (c2=0;c2<NUM_CHARSETS;c2++) {
95                         const char *n1 = charset_name((charset_t)c1);
96                         const char *n2 = charset_name((charset_t)c2);
97                         if (conv_handles[c1][c2] &&
98                             strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
99                             strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
100                                 continue;
101
102                         did_reload = True;
103
104                         if (conv_handles[c1][c2])
105                                 smb_iconv_close(conv_handles[c1][c2]);
106
107                         conv_handles[c1][c2] = smb_iconv_open(n2,n1);
108                         if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
109                                 DEBUG(0,("Conversion from %s to %s not supported\n",
110                                          charset_name((charset_t)c1), charset_name((charset_t)c2)));
111                                 conv_handles[c1][c2] = NULL;
112                         }
113                 }
114         }
115
116         if (did_reload) {
117                 /* XXX: Does this really get called every time the dos
118                  * codepage changes? */
119                 /* XXX: Is the did_reload test too strict? */
120                 init_doschar_table();
121                 init_valid_table();
122         }
123 }
124
125 /**
126  * Convert string from one encoding to another, making error checking etc
127  *
128  * @param src pointer to source string (multibyte or singlebyte)
129  * @param srclen length of the source string in bytes
130  * @param dest pointer to destination string (multibyte or singlebyte)
131  * @param destlen maximal length allowed for string
132  * @returns the number of bytes occupied in the destination
133  **/
134 size_t convert_string(charset_t from, charset_t to,
135                       void const *src, size_t srclen, 
136                       void *dest, size_t destlen)
137 {
138         size_t i_len, o_len;
139         size_t retval;
140         const char* inbuf = (const char*)src;
141         char* outbuf = (char*)dest;
142         smb_iconv_t descriptor;
143
144         if (srclen == (size_t)-1)
145                 srclen = strlen(src)+1;
146
147         lazy_initialize_conv();
148
149         descriptor = conv_handles[from][to];
150
151         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
152                 /* conversion not supported, use as is */
153                 size_t len = MIN(srclen,destlen);
154                 memcpy(dest,src,len);
155                 return len;
156         }
157
158         i_len=srclen;
159         o_len=destlen;
160         retval = smb_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
161         if(retval==(size_t)-1) {
162                 const char *reason="unknown error";
163                 switch(errno) {
164                         case EINVAL:
165                                 reason="Incomplete multibyte sequence";
166                                 break;
167                         case E2BIG:
168                                 reason="No more room"; 
169                                 DEBUG(0, ("convert_string: Required %d, available %d\n",
170                                         srclen, destlen));
171                                 /* we are not sure we need srclen bytes,
172                                   may be more, may be less.
173                                   We only know we need more than destlen
174                                   bytes ---simo */
175                                break;
176                         case EILSEQ:
177                                reason="Illegal multibyte sequence";
178                                break;
179                 }
180                 /* smb_panic(reason); */
181         }
182         return destlen-o_len;
183 }
184
185 /**
186  * Convert between character sets, allocating a new buffer for the result.
187  *
188  * @param srclen length of source buffer.
189  * @param dest always set at least to NULL
190  * @note -1 is not accepted for srclen.
191  *
192  * @returns Size in bytes of the converted string; or -1 in case of error.
193  **/
194
195 size_t convert_string_allocate(charset_t from, charset_t to,
196                                void const *src, size_t srclen, void **dest)
197 {
198         size_t i_len, o_len, destlen;
199         size_t retval;
200         const char *inbuf = (const char *)src;
201         char *outbuf, *ob;
202         smb_iconv_t descriptor;
203
204         *dest = NULL;
205
206         if (src == NULL || srclen == (size_t)-1)
207                 return (size_t)-1;
208
209         lazy_initialize_conv();
210
211         descriptor = conv_handles[from][to];
212
213         if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
214                 /* conversion not supported, return -1*/
215                 DEBUG(3, ("convert_string_allocate: conversion not supported!\n"));
216                 return -1;
217         }
218
219         destlen = MAX(srclen, 512);
220         outbuf = NULL;
221 convert:
222         destlen = destlen * 2;
223         ob = (char *)Realloc(outbuf, destlen);
224         if (!ob) {
225                 DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
226                 SAFE_FREE(outbuf);
227                 return (size_t)-1;
228         } else {
229                 outbuf = ob;
230         }
231         i_len = srclen;
232         o_len = destlen;
233         retval = smb_iconv(descriptor,
234                            &inbuf, &i_len,
235                            &outbuf, &o_len);
236         if(retval == (size_t)-1)                {
237                 const char *reason="unknown error";
238                 switch(errno) {
239                         case EINVAL:
240                                 reason="Incomplete multibyte sequence";
241                                 break;
242                         case E2BIG:
243                                 goto convert;           
244                         case EILSEQ:
245                                 reason="Illegal multibyte sequence";
246                                 break;
247                 }
248                 DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
249                 /* smb_panic(reason); */
250                 return (size_t)-1;
251         }
252         
253         destlen = destlen - o_len;
254         *dest = (char *)Realloc(ob,destlen);
255         if (!*dest) {
256                 DEBUG(0, ("convert_string_allocate: out of memory!\n"));
257                 SAFE_FREE(ob);
258                 return (size_t)-1;
259         }
260
261         return destlen;
262 }
263
264
265 /**
266  * Convert between character sets, allocating a new buffer using talloc for the result.
267  *
268  * @param srclen length of source buffer.
269  * @param dest always set at least to NULL 
270  * @note -1 is not accepted for srclen.
271  *
272  * @returns Size in bytes of the converted string; or -1 in case of error.
273  **/
274 static size_t convert_string_talloc(TALLOC_CTX *ctx, charset_t from, charset_t to,
275                                 void const *src, size_t srclen, void **dest)
276 {
277         void *alloced_string;
278         size_t dest_len;
279
280         /* FIXME: Ridiculous to allocate two buffers and then copy the string! */
281         
282         *dest = NULL;
283         dest_len=convert_string_allocate(from, to, src, srclen, &alloced_string);
284         if (dest_len == (size_t)-1)
285                 return (size_t)-1;
286         *dest = talloc_memdup(ctx, alloced_string, dest_len);
287         SAFE_FREE(alloced_string);
288         if (*dest == NULL)
289                 return (size_t)-1;
290         return dest_len;
291 }
292
293 size_t unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
294 {
295         size_t size;
296         smb_ucs2_t *buffer;
297         
298         size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
299                                        (void **) &buffer);
300         if (size == -1) {
301                 smb_panic("failed to create UCS2 buffer");
302         }
303         if (!strupper_w(buffer) && (dest == src)) {
304                 free(buffer);
305                 return srclen;
306         }
307         
308         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
309         free(buffer);
310         return size;
311 }
312
313 size_t unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
314 {
315         size_t size;
316         smb_ucs2_t *buffer;
317         
318         size = convert_string_allocate(CH_UNIX, CH_UCS2, src, srclen,
319                                        (void **) &buffer);
320         if (size == -1) {
321                 smb_panic("failed to create UCS2 buffer");
322         }
323         if (!strlower_w(buffer) && (dest == src)) {
324                 free(buffer);
325                 return srclen;
326         }
327         size = convert_string(CH_UCS2, CH_UNIX, buffer, size, dest, destlen);
328         free(buffer);
329         return size;
330 }
331
332
333 static size_t ucs2_align(const void *base_ptr, const void *p, int flags)
334 {
335         if (flags & (STR_NOALIGN|STR_ASCII))
336                 return 0;
337         return PTR_DIFF(p, base_ptr) & 1;
338 }
339
340
341 /**
342  * Copy a string from a char* unix src to a dos codepage string destination.
343  *
344  * @return the number of bytes occupied by the string in the destination.
345  *
346  * @param flags can include
347  * <dl>
348  * <dt>STR_TERMINATE</dt> <dd>means include the null termination</dd>
349  * <dt>STR_UPPER</dt> <dd>means uppercase in the destination</dd>
350  * </dl>
351  *
352  * @param dest_len the maximum length in bytes allowed in the
353  * destination.  If @p dest_len is -1 then no maximum is used.
354  **/
355 size_t push_ascii(void *dest, const char *src, size_t dest_len, int flags)
356 {
357         size_t src_len = strlen(src);
358         pstring tmpbuf;
359
360         /* treat a pstring as "unlimited" length */
361         if (dest_len == (size_t)-1)
362                 dest_len = sizeof(pstring);
363
364         if (flags & STR_UPPER) {
365                 pstrcpy(tmpbuf, src);
366                 strupper(tmpbuf);
367                 src = tmpbuf;
368         }
369
370         if (flags & STR_TERMINATE)
371                 src_len++;
372
373         return convert_string(CH_UNIX, CH_DOS, src, src_len, dest, dest_len);
374 }
375
376 size_t push_ascii_fstring(void *dest, const char *src)
377 {
378         return push_ascii(dest, src, sizeof(fstring), STR_TERMINATE);
379 }
380
381 size_t push_ascii_pstring(void *dest, const char *src)
382 {
383         return push_ascii(dest, src, sizeof(pstring), STR_TERMINATE);
384 }
385
386 /**
387  * Copy a string from a dos codepage source to a unix char* destination.
388  *
389  * The resulting string in "dest" is always null terminated.
390  *
391  * @param flags can have:
392  * <dl>
393  * <dt>STR_TERMINATE</dt>
394  * <dd>STR_TERMINATE means the string in @p src
395  * is null terminated, and src_len is ignored.</dd>
396  * </dl>
397  *
398  * @param src_len is the length of the source area in bytes.
399  * @returns the number of bytes occupied by the string in @p src.
400  **/
401 size_t pull_ascii(char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
402 {
403         size_t ret;
404
405         if (dest_len == (size_t)-1)
406                 dest_len = sizeof(pstring);
407
408         if (flags & STR_TERMINATE) {
409                 if (src_len == (size_t)-1) {
410                         src_len = strlen(src) + 1;
411                 } else {
412                         size_t len = strnlen(src, src_len);
413                         if (len < src_len)
414                                 len++;
415                         src_len = len;
416                 }
417         }
418
419         ret = convert_string(CH_DOS, CH_UNIX, src, src_len, dest, dest_len);
420
421         if (dest_len)
422                 dest[MIN(ret, dest_len-1)] = 0;
423         else
424                 dest[0] = 0;
425
426         return src_len;
427 }
428
429 size_t pull_ascii_pstring(char *dest, const void *src)
430 {
431         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
432 }
433
434 size_t pull_ascii_fstring(char *dest, const void *src)
435 {
436         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
437 }
438
439 /**
440  * Copy a string from a char* src to a unicode destination.
441  *
442  * @returns the number of bytes occupied by the string in the destination.
443  *
444  * @param flags can have:
445  *
446  * <dl>
447  * <dt>STR_TERMINATE <dd>means include the null termination.
448  * <dt>STR_UPPER     <dd>means uppercase in the destination.
449  * <dt>STR_NOALIGN   <dd>means don't do alignment.
450  * </dl>
451  *
452  * @param dest_len is the maximum length allowed in the
453  * destination. If dest_len is -1 then no maxiumum is used.
454  **/
455 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
456 {
457         size_t len=0;
458         size_t src_len = strlen(src);
459         pstring tmpbuf;
460
461         /* treat a pstring as "unlimited" length */
462         if (dest_len == (size_t)-1)
463                 dest_len = sizeof(pstring);
464
465         if (flags & STR_UPPER) {
466                 pstrcpy(tmpbuf, src);
467                 strupper(tmpbuf);
468                 src = tmpbuf;
469         }
470
471         if (flags & STR_TERMINATE)
472                 src_len++;
473
474         if (ucs2_align(base_ptr, dest, flags)) {
475                 *(char *)dest = 0;
476                 dest = (void *)((char *)dest + 1);
477                 if (dest_len) dest_len--;
478                 len++;
479         }
480
481         /* ucs2 is always a multiple of 2 bytes */
482         dest_len &= ~1;
483
484         len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
485         return len;
486 }
487
488
489 /**
490  * Copy a string from a unix char* src to a UCS2 destination,
491  * allocating a buffer using talloc().
492  *
493  * @param dest always set at least to NULL 
494  *
495  * @returns The number of bytes occupied by the string in the destination
496  *         or -1 in case of error.
497  **/
498 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
499 {
500         size_t src_len = strlen(src)+1;
501
502         *dest = NULL;
503         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
504 }
505
506
507 /**
508  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
509  *
510  * @param dest always set at least to NULL 
511  *
512  * @returns The number of bytes occupied by the string in the destination
513  *         or -1 in case of error.
514  **/
515
516 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
517 {
518         size_t src_len = strlen(src)+1;
519
520         *dest = NULL;
521         return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);  
522 }
523
524 /**
525  Copy a string from a char* src to a UTF-8 destination.
526  Return the number of bytes occupied by the string in the destination
527  Flags can have:
528   STR_TERMINATE means include the null termination
529   STR_UPPER     means uppercase in the destination
530  dest_len is the maximum length allowed in the destination. If dest_len
531  is -1 then no maxiumum is used.
532 **/
533
534 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
535 {
536         size_t src_len = strlen(src);
537         pstring tmpbuf;
538
539         /* treat a pstring as "unlimited" length */
540         if (dest_len == (size_t)-1)
541                 dest_len = sizeof(pstring);
542
543         if (flags & STR_UPPER) {
544                 pstrcpy(tmpbuf, src);
545                 strupper(tmpbuf);
546                 src = tmpbuf;
547         }
548
549         if (flags & STR_TERMINATE)
550                 src_len++;
551
552         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
553 }
554
555 size_t push_utf8_fstring(void *dest, const char *src)
556 {
557         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
558 }
559
560 /**
561  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
562  *
563  * @param dest always set at least to NULL 
564  *
565  * @returns The number of bytes occupied by the string in the destination
566  **/
567
568 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
569 {
570         size_t src_len = strlen(src)+1;
571
572         *dest = NULL;
573         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
574 }
575
576 /**
577  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
578  *
579  * @param dest always set at least to NULL 
580  *
581  * @returns The number of bytes occupied by the string in the destination
582  **/
583
584 size_t push_utf8_allocate(char **dest, const char *src)
585 {
586         size_t src_len = strlen(src)+1;
587
588         *dest = NULL;
589         return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);  
590 }
591
592 /**
593  Copy a string from a ucs2 source to a unix char* destination.
594  Flags can have:
595   STR_TERMINATE means the string in src is null terminated.
596   STR_NOALIGN   means don't try to align.
597  if STR_TERMINATE is set then src_len is ignored if it is -1.
598  src_len is the length of the source area in bytes
599  Return the number of bytes occupied by the string in src.
600  The resulting string in "dest" is always null terminated.
601 **/
602
603 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
604 {
605         size_t ret;
606
607         if (dest_len == (size_t)-1)
608                 dest_len = sizeof(pstring);
609
610         if (ucs2_align(base_ptr, src, flags)) {
611                 src = (const void *)((const char *)src + 1);
612                 if (src_len > 0)
613                         src_len--;
614         }
615
616         if (flags & STR_TERMINATE) {
617                 if (src_len == (size_t)-1) {
618                         src_len = strlen_w(src)*2 + 2;
619                 } else {
620                         size_t len = strnlen_w(src, src_len/2);
621                         if (len < src_len/2)
622                                 len++;
623                         src_len = len*2;
624                 }
625         }
626
627         /* ucs2 is always a multiple of 2 bytes */
628         if (src_len != (size_t)-1)
629                 src_len &= ~1;
630         
631         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
632         if (dest_len)
633                 dest[MIN(ret, dest_len-1)] = 0;
634         else 
635                 dest[0] = 0;
636
637         return src_len;
638 }
639
640 size_t pull_ucs2_pstring(char *dest, const void *src)
641 {
642         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
643 }
644
645 size_t pull_ucs2_fstring(char *dest, const void *src)
646 {
647         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
648 }
649
650 /**
651  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
652  *
653  * @param dest always set at least to NULL 
654  *
655  * @returns The number of bytes occupied by the string in the destination
656  **/
657
658 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
659 {
660         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
661         *dest = NULL;
662         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
663 }
664
665 /**
666  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
667  *
668  * @param dest always set at least to NULL 
669  *
670  * @returns The number of bytes occupied by the string in the destination
671  **/
672
673 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
674 {
675         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
676         *dest = NULL;
677         return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest);  
678 }
679
680 /**
681  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
682  *
683  * @param dest always set at least to NULL 
684  *
685  * @returns The number of bytes occupied by the string in the destination
686  **/
687
688 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
689 {
690         size_t src_len = strlen(src)+1;
691         *dest = NULL;
692         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);       
693 }
694
695 /**
696  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
697  *
698  * @param dest always set at least to NULL 
699  *
700  * @returns The number of bytes occupied by the string in the destination
701  **/
702
703 size_t pull_utf8_allocate(void **dest, const char *src)
704 {
705         size_t src_len = strlen(src)+1;
706         *dest = NULL;
707         return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);   
708 }
709  
710 /**
711  Copy a string from a char* src to a unicode or ascii
712  dos codepage destination choosing unicode or ascii based on the 
713  flags in the SMB buffer starting at base_ptr.
714  Return the number of bytes occupied by the string in the destination.
715  flags can have:
716   STR_TERMINATE means include the null termination.
717   STR_UPPER     means uppercase in the destination.
718   STR_ASCII     use ascii even with unicode packet.
719   STR_NOALIGN   means don't do alignment.
720  dest_len is the maximum length allowed in the destination. If dest_len
721  is -1 then no maxiumum is used.
722 **/
723
724 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)
725 {
726         if (dest_len != (size_t)-1)
727                 clobber_region(function, line, dest, dest_len);
728
729         if (!(flags & STR_ASCII) && \
730             ((flags & STR_UNICODE || \
731               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
732                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
733         }
734         return push_ascii(dest, src, dest_len, flags);
735 }
736
737
738 /**
739  Copy a string from a unicode or ascii source (depending on
740  the packet flags) to a char* destination.
741  Flags can have:
742   STR_TERMINATE means the string in src is null terminated.
743   STR_UNICODE   means to force as unicode.
744   STR_ASCII     use ascii even with unicode packet.
745   STR_NOALIGN   means don't do alignment.
746  if STR_TERMINATE is set then src_len is ignored is it is -1
747  src_len is the length of the source area in bytes.
748  Return the number of bytes occupied by the string in src.
749  The resulting string in "dest" is always null terminated.
750 **/
751
752 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)
753 {
754         if (dest_len != (size_t)-1)
755                 clobber_region(function, line, dest, dest_len);
756
757         if (!(flags & STR_ASCII) && \
758             ((flags & STR_UNICODE || \
759               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
760                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
761         }
762         return pull_ascii(dest, src, dest_len, src_len, flags);
763 }
764
765 size_t align_string(const void *base_ptr, const char *p, int flags)
766 {
767         if (!(flags & STR_ASCII) && \
768             ((flags & STR_UNICODE || \
769               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
770                 return ucs2_align(base_ptr, p, flags);
771         }
772         return 0;
773 }
774
775 /**
776  Convert from unix to ucs2 charset and return the
777  allocated and converted string or NULL if an error occurred.
778  You must provide a zero terminated string.
779  The returning string will be zero terminated.
780 **/
781
782 smb_ucs2_t *acnv_uxu2(const char *src)
783 {
784         size_t slen;
785         size_t dlen;
786         void *dest;
787         
788         slen = strlen(src) + 1;
789         dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest);
790         if (dlen == (size_t)-1)
791                 return NULL;
792         else
793                 return dest;
794 }
795
796 /**
797  Convert from dos to ucs2 charset and return the
798  allocated and converted string or NULL if an error occurred.
799  You must provide a zero terminated string.
800  The returning string will be zero terminated.
801 **/
802
803 smb_ucs2_t *acnv_dosu2(const char *src)
804 {
805         size_t slen;
806         size_t dlen;
807         void *dest;
808         
809         slen = strlen(src) + 1;
810         dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest);
811         if (dlen == (size_t)-1)
812                 return NULL;
813         else
814                 return dest;
815 }