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