2 Unix SMB/Netbios implementation.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 extern int DEBUGLEVEL;
27 * The following are the codepage to ucs2 and vica versa maps.
28 * These are dynamically loaded from a unicode translation file.
31 static smb_ucs2_t *doscp_to_ucs2;
32 static uint16 *ucs2_to_doscp;
34 static smb_ucs2_t *unixcp_to_ucs2;
35 static uint16 *ucs2_to_unixcp;
41 /*******************************************************************
42 Write a string in (little-endian) unicode format. src is in
43 the current DOS codepage. len is the length in bytes of the
44 string pointed to by dst.
46 the return value is the length of the string *without* the trailing
48 ********************************************************************/
50 int dos_PutUniCode(char *dst,const char *src, ssize_t len)
53 while (*src && (len > 2)) {
54 size_t skip = skip_multibyte_char(*src);
55 smb_ucs2_t val = (*src & 0xff);
58 * If this is a multibyte character (and all DOS/Windows
59 * codepages have at maximum 2 byte multibyte characters)
60 * then work out the index value for the unicode conversion.
64 val = ((val << 8) | src[1]);
66 SSVAL(dst,ret,doscp_to_ucs2[val]);
78 /*******************************************************************
79 Skip past some unicode strings in a buffer.
80 ********************************************************************/
82 char *skip_unicode_string(char *buf,int n)
92 /*******************************************************************
93 Return a DOS codepage version of a little-endian unicode string.
94 Hack alert: uses fixed buffer(s).
95 ********************************************************************/
97 char *dos_unistrn2(uint16 *src, int len)
99 static char lbufs[8][MAXUNI];
101 char *lbuf = lbufs[nexti];
106 for (p = lbuf; (len > 0) && (p-lbuf < MAXUNI-3) && *src; len--, src++) {
107 uint16 ucs2_val = SVAL(src,0);
108 uint16 cp_val = ucs2_to_doscp[ucs2_val];
113 *p++ = (cp_val >> 8) & 0xff;
114 *p++ = (cp_val & 0xff);
122 static char lbufs[8][MAXUNI];
125 /*******************************************************************
126 Return a DOS codepage version of a little-endian unicode string.
127 Hack alert: uses fixed buffer(s).
128 ********************************************************************/
130 char *dos_unistr2(uint16 *src)
132 char *lbuf = lbufs[nexti];
137 for (p = lbuf; *src && (p-lbuf < MAXUNI-3); src++) {
138 uint16 ucs2_val = SVAL(src,0);
139 uint16 cp_val = ucs2_to_doscp[ucs2_val];
144 *p++ = (cp_val >> 8) & 0xff;
145 *p++ = (cp_val & 0xff);
153 /*******************************************************************
154 Return a DOS codepage version of a little-endian unicode string
155 ********************************************************************/
157 char *dos_unistr2_to_str(UNISTR2 *str)
159 char *lbuf = lbufs[nexti];
161 uint16 *src = str->buffer;
162 int max_size = MIN(sizeof(str->buffer)-3, str->uni_str_len);
166 for (p = lbuf; *src && p-lbuf < max_size; src++) {
167 uint16 ucs2_val = SVAL(src,0);
168 uint16 cp_val = ucs2_to_doscp[ucs2_val];
173 *p++ = (cp_val >> 8) & 0xff;
174 *p++ = (cp_val & 0xff);
182 /*******************************************************************
183 Return a number stored in a buffer
184 ********************************************************************/
186 uint32 buffer2_to_uint32(BUFFER2 *str)
188 if (str->buf_len == 4)
189 return IVAL(str->buffer, 0);
194 /*******************************************************************
195 Return a DOS codepage version of a NOTunicode string
196 ********************************************************************/
198 char *dos_buffer2_to_str(BUFFER2 *str)
200 char *lbuf = lbufs[nexti];
202 uint16 *src = str->buffer;
203 int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
207 for (p = lbuf; *src && p-lbuf < max_size; src++) {
208 uint16 ucs2_val = SVAL(src,0);
209 uint16 cp_val = ucs2_to_doscp[ucs2_val];
214 *p++ = (cp_val >> 8) & 0xff;
215 *p++ = (cp_val & 0xff);
223 /*******************************************************************
224 Return a dos codepage version of a NOTunicode string
225 ********************************************************************/
227 char *dos_buffer2_to_multistr(BUFFER2 *str)
229 char *lbuf = lbufs[nexti];
231 uint16 *src = str->buffer;
232 int max_size = MIN(sizeof(str->buffer)-3, str->buf_len/2);
236 for (p = lbuf; p-lbuf < max_size; src++) {
240 uint16 ucs2_val = SVAL(src,0);
241 uint16 cp_val = ucs2_to_doscp[ucs2_val];
246 *p++ = (cp_val >> 8) & 0xff;
247 *p++ = (cp_val & 0xff);
256 /*******************************************************************
257 Create a null-terminated unicode string from a null-terminated DOS
259 Return number of unicode chars copied, excluding the null character.
260 Unicode strings created are in little-endian format.
261 ********************************************************************/
263 size_t dos_struni2(char *dst, const char *src, size_t max_len)
271 for (; *src && len < max_len-2; len++, dst +=2) {
272 size_t skip = skip_multibyte_char(*src);
273 smb_ucs2_t val = (*src & 0xff);
276 * If this is a multibyte character (and all DOS/Windows
277 * codepages have at maximum 2 byte multibyte characters)
278 * then work out the index value for the unicode conversion.
282 val = ((val << 8) | src[1]);
284 SSVAL(dst,0,doscp_to_ucs2[val]);
297 /*******************************************************************
298 Return a DOS codepage version of a little-endian unicode string.
299 Hack alert: uses fixed buffer(s).
300 ********************************************************************/
302 char *dos_unistr(char *buf)
304 char *lbuf = lbufs[nexti];
305 uint16 *src = (uint16 *)buf;
310 for (p = lbuf; *src && p-lbuf < MAXUNI-3; src++) {
311 uint16 ucs2_val = SVAL(src,0);
312 uint16 cp_val = ucs2_to_doscp[ucs2_val];
317 *p++ = (cp_val >> 8) & 0xff;
318 *p++ = (cp_val & 0xff);
326 /*******************************************************************
327 Strcpy for unicode strings. returns length (in num of wide chars)
328 ********************************************************************/
330 int unistrcpy(char *dst, char *src)
333 uint16 *wsrc = (uint16 *)src;
334 uint16 *wdst = (uint16 *)dst;
347 /*******************************************************************
348 free any existing maps
349 ********************************************************************/
350 static void free_maps(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
352 /* this handles identity mappings where we share the pointer */
353 if (*pp_ucs2_to_cp == *pp_cp_to_ucs2) {
354 *pp_ucs2_to_cp = NULL;
357 if (*pp_cp_to_ucs2) {
358 free(*pp_cp_to_ucs2);
359 *pp_cp_to_ucs2 = NULL;
362 if (*pp_ucs2_to_cp) {
363 free(*pp_ucs2_to_cp);
364 *pp_ucs2_to_cp = NULL;
369 /*******************************************************************
370 Build a default (null) codepage to unicode map.
371 ********************************************************************/
373 void default_unicode_map(smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
377 free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
379 if ((*pp_ucs2_to_cp = (uint16 *)malloc(2*65536)) == NULL) {
380 DEBUG(0,("default_unicode_map: malloc fail for ucs2_to_cp size %u.\n", 2*65536));
384 *pp_cp_to_ucs2 = *pp_ucs2_to_cp; /* Default map is an identity. */
385 for (i = 0; i < 65536; i++)
386 (*pp_cp_to_ucs2)[i] = i;
389 /*******************************************************************
390 Load a codepage to unicode and vica-versa map.
391 ********************************************************************/
393 BOOL load_unicode_map(const char *codepage, smb_ucs2_t **pp_cp_to_ucs2, uint16 **pp_ucs2_to_cp)
395 pstring unicode_map_file_name;
398 smb_ucs2_t *cp_to_ucs2 = *pp_cp_to_ucs2;
399 uint16 *ucs2_to_cp = *pp_ucs2_to_cp;
400 size_t cp_to_ucs2_size;
401 size_t ucs2_to_cp_size;
404 char buf[UNICODE_MAP_HEADER_SIZE];
406 DEBUG(5, ("load_unicode_map: loading unicode map for codepage %s.\n", codepage));
408 if (*codepage == '\0')
411 if(strlen(CODEPAGEDIR) + 13 + strlen(codepage) > sizeof(unicode_map_file_name)) {
412 DEBUG(0,("load_unicode_map: filename too long to load\n"));
416 pstrcpy(unicode_map_file_name, CODEPAGEDIR);
417 pstrcat(unicode_map_file_name, "/");
418 pstrcat(unicode_map_file_name, "unicode_map.");
419 pstrcat(unicode_map_file_name, codepage);
421 if(sys_stat(unicode_map_file_name,&st)!=0) {
422 DEBUG(0,("load_unicode_map: filename %s does not exist.\n",
423 unicode_map_file_name));
429 if ((size != UNICODE_MAP_HEADER_SIZE + 4*65536) && (size != UNICODE_MAP_HEADER_SIZE +(2*256 + 2*65536))) {
430 DEBUG(0,("load_unicode_map: file %s is an incorrect size for a \
431 unicode map file (size=%d).\n", unicode_map_file_name, (int)size));
435 if((fp = sys_fopen( unicode_map_file_name, "r")) == NULL) {
436 DEBUG(0,("load_unicode_map: cannot open file %s. Error was %s\n",
437 unicode_map_file_name, strerror(errno)));
441 if(fread( buf, 1, UNICODE_MAP_HEADER_SIZE, fp)!=UNICODE_MAP_HEADER_SIZE) {
442 DEBUG(0,("load_unicode_map: cannot read header from file %s. Error was %s\n",
443 unicode_map_file_name, strerror(errno)));
447 /* Check the version value */
448 if(SVAL(buf,UNICODE_MAP_VERSION_OFFSET) != UNICODE_MAP_FILE_VERSION_ID) {
449 DEBUG(0,("load_unicode_map: filename %s has incorrect version id. \
450 Needed %hu, got %hu.\n",
451 unicode_map_file_name, (uint16)UNICODE_MAP_FILE_VERSION_ID,
452 SVAL(buf,UNICODE_MAP_VERSION_OFFSET)));
456 /* Check the codepage value */
457 if(!strequal(&buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], codepage)) {
458 DEBUG(0,("load_unicode_map: codepage %s in file %s is not the same as that \
459 requested (%s).\n", &buf[UNICODE_MAP_CLIENT_CODEPAGE_OFFSET], unicode_map_file_name, codepage ));
463 ucs2_to_cp_size = 2*65536;
464 if (size == UNICODE_MAP_HEADER_SIZE + 4*65536) {
466 * This is a multibyte code page.
468 cp_to_ucs2_size = 2*65536;
471 * Single byte code page.
473 cp_to_ucs2_size = 2*256;
477 * Free any old translation tables.
480 free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
482 if ((cp_to_ucs2 = (smb_ucs2_t *)malloc(cp_to_ucs2_size)) == NULL) {
483 DEBUG(0,("load_unicode_map: malloc fail for cp_to_ucs2 size %u.\n", cp_to_ucs2_size ));
487 if ((ucs2_to_cp = (uint16 *)malloc(ucs2_to_cp_size)) == NULL) {
488 DEBUG(0,("load_unicode_map: malloc fail for ucs2_to_cp size %u.\n", ucs2_to_cp_size ));
492 if(fread( (char *)cp_to_ucs2, 1, cp_to_ucs2_size, fp)!=cp_to_ucs2_size) {
493 DEBUG(0,("load_unicode_map: cannot read cp_to_ucs2 from file %s. Error was %s\n",
494 unicode_map_file_name, strerror(errno)));
498 if(fread( (char *)ucs2_to_cp, 1, ucs2_to_cp_size, fp)!=ucs2_to_cp_size) {
499 DEBUG(0,("load_unicode_map: cannot read ucs2_to_cp from file %s. Error was %s\n",
500 unicode_map_file_name, strerror(errno)));
505 * Now ensure the 16 bit values are in the correct endianness.
508 for (i = 0; i < cp_to_ucs2_size/2; i++)
509 cp_to_ucs2[i] = SVAL(cp_to_ucs2,i*2);
511 for (i = 0; i < ucs2_to_cp_size/2; i++)
512 ucs2_to_cp[i] = SVAL(ucs2_to_cp,i*2);
516 *pp_cp_to_ucs2 = cp_to_ucs2;
517 *pp_ucs2_to_cp = ucs2_to_cp;
523 /* pseudo destructor :-) */
528 free_maps(pp_cp_to_ucs2, pp_ucs2_to_cp);
530 default_unicode_map(pp_cp_to_ucs2, pp_ucs2_to_cp);
535 /*******************************************************************
536 Load a dos codepage to unicode and vica-versa map.
537 ********************************************************************/
539 BOOL load_dos_unicode_map(int codepage)
541 fstring codepage_str;
543 slprintf(codepage_str, sizeof(fstring)-1, "%03d", codepage);
544 return load_unicode_map(codepage_str, &doscp_to_ucs2, &ucs2_to_doscp);
547 /*******************************************************************
548 Load a UNIX codepage to unicode and vica-versa map.
549 ********************************************************************/
551 BOOL load_unix_unicode_map(const char *unix_char_set)
553 fstring upper_unix_char_set;
555 fstrcpy(upper_unix_char_set, unix_char_set);
556 strupper(upper_unix_char_set);
557 return load_unicode_map(upper_unix_char_set, &unixcp_to_ucs2, &ucs2_to_unixcp);