unix_strupper, unix_strlower: Remove fixed-length static buffer that
[tprouty/samba.git] / source / 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
424         return src_len;
425 }
426
427 size_t pull_ascii_pstring(char *dest, const void *src)
428 {
429         return pull_ascii(dest, src, sizeof(pstring), -1, STR_TERMINATE);
430 }
431
432 size_t pull_ascii_fstring(char *dest, const void *src)
433 {
434         return pull_ascii(dest, src, sizeof(fstring), -1, STR_TERMINATE);
435 }
436
437 /**
438  * Copy a string from a char* src to a unicode destination.
439  *
440  * @returns the number of bytes occupied by the string in the destination.
441  *
442  * @param flags can have:
443  *
444  * <dl>
445  * <dt>STR_TERMINATE <dd>means include the null termination.
446  * <dt>STR_UPPER     <dd>means uppercase in the destination.
447  * <dt>STR_NOALIGN   <dd>means don't do alignment.
448  * </dl>
449  *
450  * @param dest_len is the maximum length allowed in the
451  * destination. If dest_len is -1 then no maxiumum is used.
452  **/
453 size_t push_ucs2(const void *base_ptr, void *dest, const char *src, size_t dest_len, int flags)
454 {
455         size_t len=0;
456         size_t src_len = strlen(src);
457         pstring tmpbuf;
458
459         /* treat a pstring as "unlimited" length */
460         if (dest_len == (size_t)-1)
461                 dest_len = sizeof(pstring);
462
463         if (flags & STR_UPPER) {
464                 pstrcpy(tmpbuf, src);
465                 strupper(tmpbuf);
466                 src = tmpbuf;
467         }
468
469         if (flags & STR_TERMINATE)
470                 src_len++;
471
472         if (ucs2_align(base_ptr, dest, flags)) {
473                 *(char *)dest = 0;
474                 dest = (void *)((char *)dest + 1);
475                 if (dest_len) dest_len--;
476                 len++;
477         }
478
479         /* ucs2 is always a multiple of 2 bytes */
480         dest_len &= ~1;
481
482         len += convert_string(CH_UNIX, CH_UCS2, src, src_len, dest, dest_len);
483         return len;
484 }
485
486
487 /**
488  * Copy a string from a unix char* src to a UCS2 destination,
489  * allocating a buffer using talloc().
490  *
491  * @param dest always set at least to NULL 
492  *
493  * @returns The number of bytes occupied by the string in the destination
494  *         or -1 in case of error.
495  **/
496 size_t push_ucs2_talloc(TALLOC_CTX *ctx, smb_ucs2_t **dest, const char *src)
497 {
498         size_t src_len = strlen(src)+1;
499
500         *dest = NULL;
501         return convert_string_talloc(ctx, CH_UNIX, CH_UCS2, src, src_len, (void **)dest);
502 }
503
504
505 /**
506  * Copy a string from a unix char* src to a UCS2 destination, allocating a buffer
507  *
508  * @param dest always set at least to NULL 
509  *
510  * @returns The number of bytes occupied by the string in the destination
511  *         or -1 in case of error.
512  **/
513
514 size_t push_ucs2_allocate(smb_ucs2_t **dest, const char *src)
515 {
516         size_t src_len = strlen(src)+1;
517
518         *dest = NULL;
519         return convert_string_allocate(CH_UNIX, CH_UCS2, src, src_len, (void **)dest);  
520 }
521
522 /**
523  Copy a string from a char* src to a UTF-8 destination.
524  Return the number of bytes occupied by the string in the destination
525  Flags can have:
526   STR_TERMINATE means include the null termination
527   STR_UPPER     means uppercase in the destination
528  dest_len is the maximum length allowed in the destination. If dest_len
529  is -1 then no maxiumum is used.
530 **/
531
532 static size_t push_utf8(void *dest, const char *src, size_t dest_len, int flags)
533 {
534         size_t src_len = strlen(src);
535         pstring tmpbuf;
536
537         /* treat a pstring as "unlimited" length */
538         if (dest_len == (size_t)-1)
539                 dest_len = sizeof(pstring);
540
541         if (flags & STR_UPPER) {
542                 pstrcpy(tmpbuf, src);
543                 strupper(tmpbuf);
544                 src = tmpbuf;
545         }
546
547         if (flags & STR_TERMINATE)
548                 src_len++;
549
550         return convert_string(CH_UNIX, CH_UTF8, src, src_len, dest, dest_len);
551 }
552
553 size_t push_utf8_fstring(void *dest, const char *src)
554 {
555         return push_utf8(dest, src, sizeof(fstring), STR_TERMINATE);
556 }
557
558 /**
559  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer using talloc
560  *
561  * @param dest always set at least to NULL 
562  *
563  * @returns The number of bytes occupied by the string in the destination
564  **/
565
566 size_t push_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
567 {
568         size_t src_len = strlen(src)+1;
569
570         *dest = NULL;
571         return convert_string_talloc(ctx, CH_UNIX, CH_UTF8, src, src_len, (void**)dest);
572 }
573
574 /**
575  * Copy a string from a unix char* src to a UTF-8 destination, allocating a buffer
576  *
577  * @param dest always set at least to NULL 
578  *
579  * @returns The number of bytes occupied by the string in the destination
580  **/
581
582 size_t push_utf8_allocate(char **dest, const char *src)
583 {
584         size_t src_len = strlen(src)+1;
585
586         *dest = NULL;
587         return convert_string_allocate(CH_UNIX, CH_UTF8, src, src_len, (void **)dest);  
588 }
589
590 /**
591  Copy a string from a ucs2 source to a unix char* destination.
592  Flags can have:
593   STR_TERMINATE means the string in src is null terminated.
594   STR_NOALIGN   means don't try to align.
595  if STR_TERMINATE is set then src_len is ignored if it is -1.
596  src_len is the length of the source area in bytes
597  Return the number of bytes occupied by the string in src.
598  The resulting string in "dest" is always null terminated.
599 **/
600
601 size_t pull_ucs2(const void *base_ptr, char *dest, const void *src, size_t dest_len, size_t src_len, int flags)
602 {
603         size_t ret;
604
605         if (dest_len == (size_t)-1)
606                 dest_len = sizeof(pstring);
607
608         if (ucs2_align(base_ptr, src, flags)) {
609                 src = (const void *)((const char *)src + 1);
610                 if (src_len > 0)
611                         src_len--;
612         }
613
614         if (flags & STR_TERMINATE) {
615                 if (src_len == (size_t)-1) {
616                         src_len = strlen_w(src)*2 + 2;
617                 } else {
618                         size_t len = strnlen_w(src, src_len/2);
619                         if (len < src_len/2)
620                                 len++;
621                         src_len = len*2;
622                 }
623         }
624
625         /* ucs2 is always a multiple of 2 bytes */
626         if (src_len != (size_t)-1)
627                 src_len &= ~1;
628         
629         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
630         if (dest_len)
631                 dest[MIN(ret, dest_len-1)] = 0;
632
633         return src_len;
634 }
635
636 size_t pull_ucs2_pstring(char *dest, const void *src)
637 {
638         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
639 }
640
641 size_t pull_ucs2_fstring(char *dest, const void *src)
642 {
643         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
644 }
645
646 /**
647  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
648  *
649  * @param dest always set at least to NULL 
650  *
651  * @returns The number of bytes occupied by the string in the destination
652  **/
653
654 size_t pull_ucs2_talloc(TALLOC_CTX *ctx, char **dest, const smb_ucs2_t *src)
655 {
656         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
657         *dest = NULL;
658         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, (void **)dest);
659 }
660
661 /**
662  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
663  *
664  * @param dest always set at least to NULL 
665  *
666  * @returns The number of bytes occupied by the string in the destination
667  **/
668
669 size_t pull_ucs2_allocate(char **dest, const smb_ucs2_t *src)
670 {
671         size_t src_len = (strlen_w(src)+1) * sizeof(smb_ucs2_t);
672         *dest = NULL;
673         return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, (void **)dest);  
674 }
675
676 /**
677  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
678  *
679  * @param dest always set at least to NULL 
680  *
681  * @returns The number of bytes occupied by the string in the destination
682  **/
683
684 size_t pull_utf8_talloc(TALLOC_CTX *ctx, char **dest, const char *src)
685 {
686         size_t src_len = strlen(src)+1;
687         *dest = NULL;
688         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, (void **)dest);       
689 }
690
691 /**
692  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
693  *
694  * @param dest always set at least to NULL 
695  *
696  * @returns The number of bytes occupied by the string in the destination
697  **/
698
699 size_t pull_utf8_allocate(void **dest, const char *src)
700 {
701         size_t src_len = strlen(src)+1;
702         *dest = NULL;
703         return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);   
704 }
705  
706 /**
707  Copy a string from a char* src to a unicode or ascii
708  dos codepage destination choosing unicode or ascii based on the 
709  flags in the SMB buffer starting at base_ptr.
710  Return the number of bytes occupied by the string in the destination.
711  flags can have:
712   STR_TERMINATE means include the null termination.
713   STR_UPPER     means uppercase in the destination.
714   STR_ASCII     use ascii even with unicode packet.
715   STR_NOALIGN   means don't do alignment.
716  dest_len is the maximum length allowed in the destination. If dest_len
717  is -1 then no maxiumum is used.
718 **/
719
720 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)
721 {
722         if (dest_len != (size_t)-1)
723                 clobber_region(function, line, dest, dest_len);
724
725         if (!(flags & STR_ASCII) && \
726             ((flags & STR_UNICODE || \
727               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
728                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
729         }
730         return push_ascii(dest, src, dest_len, flags);
731 }
732
733
734 /**
735  Copy a string from a unicode or ascii source (depending on
736  the packet flags) to a char* destination.
737  Flags can have:
738   STR_TERMINATE means the string in src is null terminated.
739   STR_UNICODE   means to force as unicode.
740   STR_ASCII     use ascii even with unicode packet.
741   STR_NOALIGN   means don't do alignment.
742  if STR_TERMINATE is set then src_len is ignored is it is -1
743  src_len is the length of the source area in bytes.
744  Return the number of bytes occupied by the string in src.
745  The resulting string in "dest" is always null terminated.
746 **/
747
748 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)
749 {
750         if (dest_len != (size_t)-1)
751                 clobber_region(function, line, dest, dest_len);
752
753         if (!(flags & STR_ASCII) && \
754             ((flags & STR_UNICODE || \
755               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
756                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
757         }
758         return pull_ascii(dest, src, dest_len, src_len, flags);
759 }
760
761 size_t align_string(const void *base_ptr, const char *p, int flags)
762 {
763         if (!(flags & STR_ASCII) && \
764             ((flags & STR_UNICODE || \
765               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
766                 return ucs2_align(base_ptr, p, flags);
767         }
768         return 0;
769 }
770
771 /**
772  Convert from unix to ucs2 charset and return the
773  allocated and converted string or NULL if an error occurred.
774  You must provide a zero terminated string.
775  The returning string will be zero terminated.
776 **/
777
778 smb_ucs2_t *acnv_uxu2(const char *src)
779 {
780         size_t slen;
781         size_t dlen;
782         void *dest;
783         
784         slen = strlen(src) + 1;
785         dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest);
786         if (dlen == (size_t)-1)
787                 return NULL;
788         else
789                 return dest;
790 }
791
792 /**
793  Convert from dos to ucs2 charset and return the
794  allocated and converted string or NULL if an error occurred.
795  You must provide a zero terminated string.
796  The returning string will be zero terminated.
797 **/
798
799 smb_ucs2_t *acnv_dosu2(const char *src)
800 {
801         size_t slen;
802         size_t dlen;
803         void *dest;
804         
805         slen = strlen(src) + 1;
806         dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest);
807         if (dlen == (size_t)-1)
808                 return NULL;
809         else
810                 return dest;
811 }