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