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    
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 *ob;
253         size_t dest_len;
254
255         *dest = NULL;
256         dest_len=convert_string_allocate(from, to, src, srclen, (void **)&ob);
257         if (dest_len == -1)
258                 return -1;
259         *dest = talloc_strdup(ctx, (char *)ob);
260         SAFE_FREE(ob);
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, void **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, 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         src_len &= ~1;
566         
567         ret = convert_string(CH_UCS2, CH_UNIX, src, src_len, dest, dest_len);
568         if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
569
570         return src_len;
571 }
572
573 int pull_ucs2_pstring(char *dest, const void *src)
574 {
575         return pull_ucs2(NULL, dest, src, sizeof(pstring), -1, STR_TERMINATE);
576 }
577
578 int pull_ucs2_fstring(char *dest, const void *src)
579 {
580         return pull_ucs2(NULL, dest, src, sizeof(fstring), -1, STR_TERMINATE);
581 }
582
583 /**
584  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer using talloc
585  *
586  * @param dest always set at least to NULL 
587  *
588  * @retval The number of bytes occupied by the string in the destination
589  **/
590 int pull_ucs2_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
591 {
592         int src_len = strlen(src)+1;
593         *dest = NULL;
594         return convert_string_talloc(ctx, CH_UCS2, CH_UNIX, src, src_len, dest);        
595 }
596
597 /**
598  * Copy a string from a UCS2 src to a unix char * destination, allocating a buffer
599  *
600  * @param dest always set at least to NULL 
601  *
602  * @retval The number of bytes occupied by the string in the destination
603  **/
604 int pull_ucs2_allocate(void **dest, const char *src)
605 {
606         int src_len = strlen(src)+1;
607         *dest = NULL;
608         return convert_string_allocate(CH_UCS2, CH_UNIX, src, src_len, dest);   
609 }
610
611 /****************************************************************************
612 copy a string from a utf-8 source to a unix char* destination
613 flags can have:
614   STR_TERMINATE means the string in src is null terminated
615 if STR_TERMINATE is set then src_len is ignored
616 src_len is the length of the source area in bytes
617 return the number of bytes occupied by the string in src
618 the resulting string in "dest" is always null terminated
619 ****************************************************************************/
620 int pull_utf8(char *dest, const void *src, int dest_len, int src_len, int flags)
621 {
622         int ret;
623
624         if (dest_len == -1) {
625                 dest_len = sizeof(pstring);
626         }
627
628         if (flags & STR_TERMINATE) {
629                 if (src_len == -1) {
630                         src_len = strlen(src) + 1;
631                 } else {
632                         int len = strnlen(src, src_len);
633                         if (len < src_len) len++;
634                         src_len = len;
635                 }
636         }
637
638         ret = convert_string(CH_UTF8, CH_UNIX, src, src_len, dest, dest_len);
639         if (dest_len) dest[MIN(ret, dest_len-1)] = 0;
640
641         return src_len;
642 }
643
644 int pull_utf8_pstring(char *dest, const void *src)
645 {
646         return pull_utf8(dest, src, sizeof(pstring), -1, STR_TERMINATE);
647 }
648
649 int pull_utf8_fstring(char *dest, const void *src)
650 {
651         return pull_utf8(dest, src, sizeof(fstring), -1, STR_TERMINATE);
652 }
653
654 /**
655  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer using talloc
656  *
657  * @param dest always set at least to NULL 
658  *
659  * @retval The number of bytes occupied by the string in the destination
660  **/
661 int pull_utf8_talloc(TALLOC_CTX *ctx, void **dest, const char *src)
662 {
663         int src_len = strlen(src)+1;
664         *dest = NULL;
665         return convert_string_talloc(ctx, CH_UTF8, CH_UNIX, src, src_len, dest);        
666 }
667
668 /**
669  * Copy a string from a UTF-8 src to a unix char * destination, allocating a buffer
670  *
671  * @param dest always set at least to NULL 
672  *
673  * @retval The number of bytes occupied by the string in the destination
674  **/
675 int pull_utf8_allocate(void **dest, const char *src)
676 {
677         int src_len = strlen(src)+1;
678         *dest = NULL;
679         return convert_string_allocate(CH_UTF8, CH_UNIX, src, src_len, dest);   
680 }
681  
682 /****************************************************************************
683 copy a string from a char* src to a unicode or ascii
684 dos codepage destination choosing unicode or ascii based on the 
685 flags in the SMB buffer starting at base_ptr
686 return the number of bytes occupied by the string in the destination
687 flags can have:
688   STR_TERMINATE means include the null termination
689   STR_UPPER     means uppercase in the destination
690   STR_ASCII     use ascii even with unicode packet
691   STR_NOALIGN   means don't do alignment
692 dest_len is the maximum length allowed in the destination. If dest_len
693 is -1 then no maxiumum is used
694 ****************************************************************************/
695 int push_string(const void *base_ptr, void *dest, const char *src, int dest_len, int flags)
696 {
697         if (!(flags & STR_ASCII) && \
698             ((flags & STR_UNICODE || \
699               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
700                 return push_ucs2(base_ptr, dest, src, dest_len, flags);
701         }
702         return push_ascii(dest, src, dest_len, flags);
703 }
704
705
706 /****************************************************************************
707 copy a string from a unicode or ascii source (depending on
708 the packet flags) to a char* destination
709 flags can have:
710   STR_TERMINATE means the string in src is null terminated
711   STR_UNICODE   means to force as unicode
712   STR_ASCII     use ascii even with unicode packet
713   STR_NOALIGN   means don't do alignment
714 if STR_TERMINATE is set then src_len is ignored is it is -1
715 src_len is the length of the source area in bytes
716 return the number of bytes occupied by the string in src
717 the resulting string in "dest" is always null terminated
718 ****************************************************************************/
719 int pull_string(const void *base_ptr, char *dest, const void *src, int dest_len, int src_len, 
720                 int flags)
721 {
722         if (!(flags & STR_ASCII) && \
723             ((flags & STR_UNICODE || \
724               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
725                 return pull_ucs2(base_ptr, dest, src, dest_len, src_len, flags);
726         }
727         return pull_ascii(dest, src, dest_len, src_len, flags);
728 }
729
730 int align_string(const void *base_ptr, const char *p, int flags)
731 {
732         if (!(flags & STR_ASCII) && \
733             ((flags & STR_UNICODE || \
734               (SVAL(base_ptr, smb_flg2) & FLAGS2_UNICODE_STRINGS)))) {
735                 return ucs2_align(base_ptr, p, flags);
736         }
737         return 0;
738 }
739
740
741
742 /****************************************************************************
743 convert from ucs2 to unix charset and return the
744 allocated and converted string or NULL if an error occurred.
745 you must provide a zero terminated string.
746 the returning string will be zero terminated.
747 ****************************************************************************/
748 char *acnv_u2ux(const smb_ucs2_t *src)
749 {
750         size_t slen;
751         size_t dlen;
752         void *dest;
753         
754         slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t);
755         dlen = convert_string_allocate(CH_UCS2, CH_UNIX, src, slen, &dest);
756         if (dlen == -1) return NULL;
757         else return dest;
758 }
759
760 /****************************************************************************
761 convert from unix to ucs2 charset and return the
762 allocated and converted string or NULL if an error occurred.
763 you must provide a zero terminated string.
764 the returning string will be zero terminated.
765 ****************************************************************************/
766 smb_ucs2_t *acnv_uxu2(const char *src)
767 {
768         size_t slen;
769         size_t dlen;
770         void *dest;
771         
772         slen = strlen(src) + 1;
773         dlen = convert_string_allocate(CH_UNIX, CH_UCS2, src, slen, &dest);
774         if (dlen == -1) return NULL;
775         else return dest;
776 }
777
778 /****************************************************************************
779 convert from ucs2 to dos charset and return the
780 allocated and converted string or NULL if an error occurred.
781 you must provide a zero terminated string.
782 the returning string will be zero terminated.
783 ****************************************************************************/
784 char *acnv_u2dos(const smb_ucs2_t *src)
785 {
786         size_t slen;
787         size_t dlen;
788         void *dest;
789         
790         slen = (strlen_w(src) + 1) * sizeof(smb_ucs2_t);
791         dlen = convert_string_allocate(CH_UCS2, CH_DOS, src, slen, &dest);
792         if (dlen == -1) return NULL;
793         else 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 smb_ucs2_t *acnv_dosu2(const char *src)
803 {
804         size_t slen;
805         size_t dlen;
806         void *dest;
807         
808         slen = strlen(src) + 1;
809         dlen = convert_string_allocate(CH_DOS, CH_UCS2, src, slen, &dest);
810         if (dlen == -1) return NULL;
811         else return dest;
812 }