diff options
Diffstat (limited to 'usr/src/common')
-rw-r--r-- | usr/src/common/smbsrv/smb_match.c | 45 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_msgbuf.c | 36 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_native.c | 10 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_netbios_util.c | 11 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_oem.c | 747 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_opmlang.c | 127 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_strcase.c | 388 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_string.c | 326 | ||||
-rw-r--r-- | usr/src/common/smbsrv/smb_utf8.c | 63 |
9 files changed, 579 insertions, 1174 deletions
diff --git a/usr/src/common/smbsrv/smb_match.c b/usr/src/common/smbsrv/smb_match.c index 0d612b3daf..88758926fe 100644 --- a/usr/src/common/smbsrv/smb_match.c +++ b/usr/src/common/smbsrv/smb_match.c @@ -30,7 +30,8 @@ #include <sys/types.h> #include <sys/sunddi.h> #endif -#include <smbsrv/ctype.h> +#include <smbsrv/string.h> +#include <smbsrv/smb.h> /* * Maximum recursion depth for the wildcard match functions. @@ -80,8 +81,8 @@ smb_match_private(const char *patn, const char *str, int *depth) for (;;) { switch (*patn) { - case 0: - return (*str == 0); + case '\0': + return (*str == '\0'); case '?': if (*str != 0) { @@ -95,7 +96,7 @@ smb_match_private(const char *patn, const char *str, int *depth) case '*': patn += strspn(patn, "*"); - if (*patn == 0) + if (*patn == '\0') return (1); if ((*depth)++ >= SMB_MATCH_DEPTH_MAX) @@ -128,7 +129,8 @@ smb_match83(char *patn, char *str83) char name83[14]; ptr = name83; - for (avail = 8; (avail > 0) && (*patn != '.') && (*patn != 0); + for (avail = SMB_NAME83_BASELEN; + (avail > 0) && (*patn != '.') && (*patn != 0); avail--) { *(ptr++) = *(patn++); } @@ -141,7 +143,7 @@ smb_match83(char *patn, char *str83) else if (*patn != 0) return (0); - for (avail = 3; (avail > 0) && (*patn != 0); avail--) { + for (avail = SMB_NAME83_EXTLEN; (avail > 0) && (*patn != 0); avail--) { *(ptr++) = *(patn++); } if (*patn != 0) @@ -187,8 +189,10 @@ smb_match_ci(char *patn, char *str) static int smb_match_ci_private(const char *patn, const char *str, int *depth) { - const char *p; - int rc; + const char *p; + smb_wchar_t wc1, wc2; + int nbytes1, nbytes2; + int rc; /* * "<" is a special pattern that matches only those names that do @@ -204,8 +208,8 @@ smb_match_ci_private(const char *patn, const char *str, int *depth) for (;;) { switch (*patn) { - case 0: - return (*str == 0); + case '\0': + return (*str == '\0'); case '?': if (*str != 0) { @@ -221,7 +225,7 @@ smb_match_ci_private(const char *patn, const char *str, int *depth) case '*': patn += strspn(patn, "*"); - if (*patn == 0) + if (*patn == '\0') return (1); if ((*depth)++ >= SMB_MATCH_DEPTH_MAX) @@ -236,17 +240,20 @@ smb_match_ci_private(const char *patn, const char *str, int *depth) return (0); default: - if (*str != *patn) { - int c1 = *str; - int c2 = *patn; + nbytes1 = smb_mbtowc(&wc1, patn, MTS_MB_CHAR_MAX); + nbytes2 = smb_mbtowc(&wc2, str, MTS_MB_CHAR_MAX); + if ((nbytes1 == -1) || (nbytes2 == -1)) + return (-1); - c1 = mts_tolower(c1); - c2 = mts_tolower(c2); - if (c1 != c2) + if (wc1 != wc2) { + wc1 = smb_tolower(wc1); + wc2 = smb_tolower(wc2); + if (wc1 != wc2) return (0); } - str++; - patn++; + + patn += nbytes1; + str += nbytes2; continue; } } diff --git a/usr/src/common/smbsrv/smb_msgbuf.c b/usr/src/common/smbsrv/smb_msgbuf.c index d456dac683..2530a4f5ef 100644 --- a/usr/src/common/smbsrv/smb_msgbuf.c +++ b/usr/src/common/smbsrv/smb_msgbuf.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Msgbuf buffer management implementation. The smb_msgbuf interface is * typically used to encode or decode SMB data using sprintf/scanf @@ -52,7 +50,7 @@ static int buf_decode(smb_msgbuf_t *, char *, va_list ap); static int buf_encode(smb_msgbuf_t *, char *, va_list ap); static void *smb_msgbuf_malloc(smb_msgbuf_t *, size_t); static int smb_msgbuf_chkerc(char *text, int erc); -static void buf_decode_wcs(mts_wchar_t *, mts_wchar_t *, int wcstrlen); +static void buf_decode_wcs(smb_wchar_t *, smb_wchar_t *, int wcstrlen); /* * Returns the offset or number of bytes used within the buffer. @@ -221,7 +219,7 @@ buf_decode(smb_msgbuf_t *mb, char *fmt, va_list ap) uint16_t *wvalp; uint32_t *lvalp; uint64_t *llvalp; - mts_wchar_t *wcs; + smb_wchar_t *wcs; int repc; int rc; @@ -328,7 +326,7 @@ buf_decode(smb_msgbuf_t *mb, char *fmt, va_list ap) if ((cvalp = smb_msgbuf_malloc(mb, ival * 2)) == 0) return (SMB_MSGBUF_UNDERFLOW); - if ((ival = mts_stombs((char *)cvalp, + if ((ival = smb_stombs((char *)cvalp, (char *)mb->scan, ival * 2)) == (uint32_t)-1) { return (SMB_MSGBUF_DATA_ERROR); @@ -349,12 +347,12 @@ unicode_translation: */ smb_msgbuf_word_align(mb); /*LINTED E_BAD_PTR_CAST_ALIGN*/ - wcs = (mts_wchar_t *)mb->scan; + wcs = (smb_wchar_t *)mb->scan; /* count the null wchar */ - repc = sizeof (mts_wchar_t); + repc = sizeof (smb_wchar_t); while (*wcs++) - repc += sizeof (mts_wchar_t); + repc += sizeof (smb_wchar_t); if (smb_msgbuf_has_space(mb, repc) == 0) return (SMB_MSGBUF_UNDERFLOW); @@ -364,15 +362,15 @@ unicode_translation: return (SMB_MSGBUF_UNDERFLOW); /*LINTED E_BAD_PTR_CAST_ALIGN*/ - buf_decode_wcs(wcs, (mts_wchar_t *)mb->scan, - repc / sizeof (mts_wchar_t)); + buf_decode_wcs(wcs, (smb_wchar_t *)mb->scan, + repc / sizeof (smb_wchar_t)); /* Get space for translated string */ if ((cvalp = smb_msgbuf_malloc(mb, repc * 2)) == 0) return (SMB_MSGBUF_UNDERFLOW); /* Translate string */ - (void) mts_wcstombs((char *)cvalp, wcs, repc * 2); + (void) smb_wcstombs((char *)cvalp, wcs, repc * 2); cvalpp = va_arg(ap, uint8_t **); *cvalpp = cvalp; @@ -450,7 +448,7 @@ buf_encode(smb_msgbuf_t *mb, char *fmt, va_list ap) uint32_t ival; uint8_t *cvalp; uint8_t c; - mts_wchar_t wcval; + smb_wchar_t wcval; int count; int repc = 1; int rc; @@ -559,7 +557,7 @@ buf_encode(smb_msgbuf_t *mb, char *fmt, va_list ap) return (SMB_MSGBUF_OVERFLOW); ival = - mts_mbstos((char *)mb->scan, (const char *)cvalp); + smb_mbstos((char *)mb->scan, (const char *)cvalp); mb->scan += ival + 1; break; @@ -573,11 +571,11 @@ unicode_translation: for (;;) { rc = smb_msgbuf_has_space(mb, - sizeof (mts_wchar_t)); + sizeof (smb_wchar_t)); if (rc == 0) return (SMB_MSGBUF_OVERFLOW); - count = mts_mbtowc(&wcval, (const char *)cvalp, + count = smb_mbtowc(&wcval, (const char *)cvalp, MTS_MB_CHAR_MAX); if (count < 0) { @@ -605,11 +603,11 @@ unicode_translation: if ((mb->flags & SMB_MSGBUF_NOTERM) == 0) mb->scan += - sizeof (mts_wchar_t); + sizeof (smb_wchar_t); break; } - mb->scan += sizeof (mts_wchar_t); + mb->scan += sizeof (smb_wchar_t); cvalp += count; } break; @@ -697,7 +695,7 @@ smb_msgbuf_chkerc(char *text, int erc) } static void -buf_decode_wcs(mts_wchar_t *dst_wcstr, mts_wchar_t *src_wcstr, int wcstrlen) +buf_decode_wcs(smb_wchar_t *dst_wcstr, smb_wchar_t *src_wcstr, int wcstrlen) { int i; diff --git a/usr/src/common/smbsrv/smb_native.c b/usr/src/common/smbsrv/smb_native.c index cc1837809e..8dc67d42f1 100644 --- a/usr/src/common/smbsrv/smb_native.c +++ b/usr/src/common/smbsrv/smb_native.c @@ -105,7 +105,7 @@ smbnative_os_value(const char *native_os) name = os_table[i].sn_name; len = strlen(name); - if (utf8_strncasecmp(name, native_os, len) == 0) + if (smb_strcasecmp(name, native_os, len) == 0) return (os_table[i].sn_value); } @@ -159,8 +159,8 @@ smbnative_lm_value(const char *native_lm) name = lm_table[i].sn_name; len = strlen(name); - if ((utf8_strncasecmp(name, native_lm, len) == 0) || - (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) { + if ((smb_strcasecmp(name, native_lm, len) == 0) || + (smb_strcasecmp(&name[1], native_lm, len - 1) == 0)) { return (lm_table[i].sn_value); } } @@ -209,8 +209,8 @@ smbnative_pdc_value(const char *native_lm) name = pdc_table[i].sn_name; len = strlen(name); - if ((utf8_strncasecmp(name, native_lm, len) == 0) || - (utf8_strncasecmp(&name[1], native_lm, len - 1) == 0)) { + if ((smb_strcasecmp(name, native_lm, len) == 0) || + (smb_strcasecmp(&name[1], native_lm, len - 1) == 0)) { return (pdc_table[i].sn_value); } } diff --git a/usr/src/common/smbsrv/smb_netbios_util.c b/usr/src/common/smbsrv/smb_netbios_util.c index 1bd47f80bc..a0e0f480f1 100644 --- a/usr/src/common/smbsrv/smb_netbios_util.c +++ b/usr/src/common/smbsrv/smb_netbios_util.c @@ -19,12 +19,10 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef _KERNEL #include <sys/types.h> #include <sys/sunddi.h> @@ -32,7 +30,6 @@ #include <string.h> #endif #include <smbsrv/string.h> -#include <smbsrv/ctype.h> #include <smbsrv/netbios.h> static int domainname_is_valid(char *domain_name); @@ -286,7 +283,7 @@ netbios_first_level_name_decode(char *in, char *name, char *scope) * to Appendix 1 - Domain Name Syntax Specification in RFC883. */ if (domainname_is_valid(scope)) { - (void) utf8_strupr(scope); + (void) smb_strupr(scope); /*LINTED E_PTRDIFF_OVERFLOW*/ return (cp - in); } @@ -377,14 +374,14 @@ domainname_is_valid(char *domain_name) } if (first_char) { - if (mts_isalpha_ascii(*name) == 0) + if (smb_isalpha_ascii(*name) == 0) return (0); first_char = 0; continue; } - if (mts_isalnum_ascii(*name) || dns_is_allowed(*name)) + if (smb_isalnum_ascii(*name) || dns_is_allowed(*name)) continue; return (0); diff --git a/usr/src/common/smbsrv/smb_oem.c b/usr/src/common/smbsrv/smb_oem.c index 4dca80402b..92d6aec029 100644 --- a/usr/src/common/smbsrv/smb_oem.c +++ b/usr/src/common/smbsrv/smb_oem.c @@ -19,108 +19,83 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - /* * Support for oem <-> unicode translations. */ #ifndef _KERNEL -#include <stdio.h> #include <stdlib.h> #include <thread.h> #include <synch.h> #include <string.h> +#else +#include <sys/ksynch.h> #endif /* _KERNEL */ + +#include <sys/byteorder.h> #include <smbsrv/alloc.h> #include <smbsrv/string.h> -#include <smbsrv/oem.h> -#include <sys/byteorder.h> + /* - * name: Name used to show on the telnet/GUI. - * filename: The actual filename contains the codepage. - * doublebytes: The codepage is double or single byte. - * oempage: The oempage is used to convert Unicode to OEM chars. - * Memory needs to be allocated for value field of oempage - * to store the entire table. - * unipage: The unipage is used to convert OEM to Unicode chars. - * Memory needs to be allocated for value field of unipage - * to store the entire table. - * valid: This field indicates if the page is valid or not. - * ref: This ref count is used to keep track of the usage of BOTH - * oempage and unipage. - * Note: If the cpid of the table is changed, please change the - * codepage_id in oem.h as well. + * cpid The oemcpg_table index for this oempage. + * value The conversion values. + */ +typedef struct oempage { + uint32_t cpid; + smb_wchar_t *value; +} oempage_t; + +/* + * filename The actual filename contains the codepage. + * bytesperchar The codepage uses double or single bytes per char. + * oempage The oempage is used to convert Unicode characters to + * OEM characters. Memory needs to be allocated for + * the value field of oempage to store the table. + * ucspage The unicode page is used to convert OEM characters + * to Unicode characters. Memory needs to be allocated + * for the value field of ucspage to store the table. + * valid True if the codepage has been initialized. */ typedef struct oem_codepage { - char *filename; - unsigned int bytesperchar; - oempage_t oempage; - oempage_t unicodepage; - unsigned int valid; - unsigned int ref; + char *filename; + uint32_t bytesperchar; + oempage_t oempage; + oempage_t ucspage; + boolean_t valid; } oem_codepage_t; -static oem_codepage_t oemcp_table[] = { - {"850.cpg", 1, {0, 0}, {0, 0}, 0, 0}, /* Multilingual Latin1 */ - {"950.cpg", 2, {1, 0}, {1, 0}, 0, 0}, /* Chinese Traditional */ - {"1252.cpg", 1, {2, 0}, {2, 0}, 0, 0}, /* MS Latin1 */ - {"949.cpg", 2, {3, 0}, {3, 0}, 0, 0}, /* Korean */ - {"936.cpg", 2, {4, 0}, {4, 0}, 0, 0}, /* Chinese Simplified */ - {"932.cpg", 2, {5, 0}, {5, 0}, 0, 0}, /* Japanese */ - {"852.cpg", 1, {6, 0}, {6, 0}, 0, 0}, /* Multilingual Latin2 */ - {"1250.cpg", 1, {7, 0}, {7, 0}, 0, 0}, /* MS Latin2 */ - {"1253.cpg", 1, {8, 0}, {8, 0}, 0, 0}, /* MS Greek */ - {"737.cpg", 1, {9, 0}, {9, 0}, 0, 0}, /* Greek */ - {"1254.cpg", 1, {10, 0}, {10, 0}, 0, 0}, /* MS Turkish */ - {"857.cpg", 1, {11, 0}, {11, 0}, 0, 0}, /* Multilingual Latin5 */ - {"1251.cpg", 1, {12, 0}, {12, 0}, 0, 0}, /* MS Cyrillic */ - {"866.cpg", 1, {13, 0}, {13, 0}, 0, 0}, /* Cyrillic II */ - {"1255.cpg", 1, {14, 0}, {14, 0}, 0, 0}, /* MS Hebrew */ - {"862.cpg", 1, {15, 0}, {15, 0}, 0, 0}, /* Hebrew */ - {"1256.cpg", 1, {16, 0}, {16, 0}, 0, 0}, /* MS Arabic */ - {"720.cpg", 1, {17, 0}, {17, 0}, 0, 0} /* Arabic */ -}; - -static language lang_table[] = { - {"Arabic", OEM_CP_IND_720, OEM_CP_IND_1256}, - {"Brazilian", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Chinese Traditional", OEM_CP_IND_950, OEM_CP_IND_950}, - {"Chinese Simplified", OEM_CP_IND_936, OEM_CP_IND_936}, - {"Czech", OEM_CP_IND_852, OEM_CP_IND_1250}, - {"Danish", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Dutch", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"English", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Finnish", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"French", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"German", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Greek", OEM_CP_IND_737, OEM_CP_IND_1253}, - {"Hebrew", OEM_CP_IND_862, OEM_CP_IND_1255}, - {"Hungarian", OEM_CP_IND_852, OEM_CP_IND_1250}, - {"Italian", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Japanese", OEM_CP_IND_932, OEM_CP_IND_932}, - {"Korean", OEM_CP_IND_949, OEM_CP_IND_949}, - {"Norwegian", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Polish", OEM_CP_IND_852, OEM_CP_IND_1250}, - {"Russian", OEM_CP_IND_866, OEM_CP_IND_1251}, - {"Slovak", OEM_CP_IND_852, OEM_CP_IND_1250}, - {"Slovenian", OEM_CP_IND_852, OEM_CP_IND_1250}, - {"Spanish", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Swedish", OEM_CP_IND_850, OEM_CP_IND_1252}, - {"Turkish", OEM_CP_IND_857, OEM_CP_IND_1254} +static oem_codepage_t oemcpg_table[] = { + {"850.cpg", 1, {0, 0}, {0, 0}, 0}, /* Multilingual Latin1 */ + {"950.cpg", 2, {1, 0}, {1, 0}, 0}, /* Chinese Traditional */ + {"1252.cpg", 1, {2, 0}, {2, 0}, 0}, /* MS Latin1 */ + {"949.cpg", 2, {3, 0}, {3, 0}, 0}, /* Korean */ + {"936.cpg", 2, {4, 0}, {4, 0}, 0}, /* Chinese Simplified */ + {"932.cpg", 2, {5, 0}, {5, 0}, 0}, /* Japanese */ + {"852.cpg", 1, {6, 0}, {6, 0}, 0}, /* Multilingual Latin2 */ + {"1250.cpg", 1, {7, 0}, {7, 0}, 0}, /* MS Latin2 */ + {"1253.cpg", 1, {8, 0}, {8, 0}, 0}, /* MS Greek */ + {"737.cpg", 1, {9, 0}, {9, 0}, 0}, /* Greek */ + {"1254.cpg", 1, {10, 0}, {10, 0}, 0}, /* MS Turkish */ + {"857.cpg", 1, {11, 0}, {11, 0}, 0}, /* Multilingual Latin5 */ + {"1251.cpg", 1, {12, 0}, {12, 0}, 0}, /* MS Cyrillic */ + {"866.cpg", 1, {13, 0}, {13, 0}, 0}, /* Cyrillic II */ + {"1255.cpg", 1, {14, 0}, {14, 0}, 0}, /* MS Hebrew */ + {"862.cpg", 1, {15, 0}, {15, 0}, 0}, /* Hebrew */ + {"1256.cpg", 1, {16, 0}, {16, 0}, 0}, /* MS Arabic */ + {"720.cpg", 1, {17, 0}, {17, 0}, 0} /* Arabic */ }; - +#define MAX_OEMPAGES (sizeof (oemcpg_table) / sizeof (oemcpg_table[0])) +#define MAX_UNICODE_IDX 65536 /* - * The oem_default_smb_cp is the default smb codepage for English. - * It is actually codepage 850. + * The default SMB OEM codepage for English is codepage 850. */ -mts_wchar_t oem_default_smb_cp[256] = { +smb_wchar_t oem_codepage_850[256] = { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, @@ -155,13 +130,10 @@ mts_wchar_t oem_default_smb_cp[256] = { 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 }; - - /* - * The oem_default_telnet_cp is the default telnet codepage for English. - * It is actually codepage 1252. + * The default telnet OEM codepage for English is codepage 1252. */ -mts_wchar_t oem_default_telnet_cp[256] = { +smb_wchar_t oem_codepage_1252[256] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, @@ -196,567 +168,206 @@ mts_wchar_t oem_default_telnet_cp[256] = { 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF }; - -#define MAX_OEMPAGES (sizeof (oemcp_table) / sizeof (oemcp_table[0])) -#define MAX_UNI_IDX 65536 - - - -/* - * oem_codepage_bytesperchar - * - * This function returns the max bytes per oem char for the specified - * oem table. This basically shows if the oem codepage is single or - * double bytes. - */ -static unsigned int -oem_codepage_bytesperchar(unsigned int cpid) -{ - if (cpid >= MAX_OEMPAGES) - return (0); - else - return (oemcp_table[cpid].bytesperchar); -} - - +static oempage_t *oem_get_oempage(uint32_t); +static oempage_t *oem_get_ucspage(uint32_t); +static void oem_codepage_init(uint32_t); +static void oem_codepage_setup(uint32_t); /* - * oem_get_codepage_path + * Convert a unicode string to an oem string. * - * This function will get the codepage path. - */ -const char * -oem_get_codepage_path(void) -{ -#ifdef PBSHORTCUT /* */ - const char *path = getenv("codepage.oem.directory"); - if (path == 0) - return ("/"); - else - return (path); -#else /* PBSHORTCUT */ - return ("/"); -#endif /* PBSHORTCUT */ -} - -/* - * oem_codepage_init + * The conversion will stop at the end of the unicode string + * or when (nbytes - 1) oem characters have been stored. * - * This function will init oem page via the cpid of the oem table. - * The function oem_codepage_free must be called when the oempage is - * no longer needed to free up the allocated memory. If the codepage is - * successfully initialized, zero will be the return value; otherwise - * -1 will be the return value. - */ -int -oem_codepage_init(unsigned int cpid) -{ -#ifndef _KERNEL - FILE *fp; - static mutex_t mutex; - char buf[32]; - char filePath[100]; -#endif /* _KERNEL */ - unsigned int max_oem_index; - const char *codepagePath = oem_get_codepage_path(); - mts_wchar_t *default_oem_cp = 0; - oem_codepage_t *oemcp; - - /* - * The OEM codepages 850 and 1252 are stored in kernel; therefore, - * no need for codepagePath to be defined to work. - */ - if (cpid >= MAX_OEMPAGES || - (codepagePath == 0 && - cpid != oem_default_smb_cpid && cpid != oem_default_telnet_cpid)) - return (-1); - - max_oem_index = 1 << oem_codepage_bytesperchar(cpid) * 8; - /* - * Use mutex so no two same index can be initialize - * at the same time. - */ -#ifndef _KERNEL - (void) mutex_lock(&mutex); -#endif /* _KERNEL */ - - oemcp = &oemcp_table[cpid]; - if (oemcp->valid) { - oemcp->valid++; -#ifndef _KERNEL - (void) mutex_unlock(&mutex); -#endif /* _KERNEL */ - return (0); - } - - oemcp->oempage.value = - MEM_ZALLOC("oem", max_oem_index * sizeof (mts_wchar_t)); - if (oemcp->oempage.value == 0) { -#ifndef _KERNEL - (void) mutex_unlock(&mutex); -#endif /* _KERNEL */ - return (-1); - } - - oemcp->unicodepage.value = - MEM_ZALLOC("oem", MAX_UNI_IDX * sizeof (mts_wchar_t)); - if (oemcp->unicodepage.value == 0) { - MEM_FREE("oem", oemcp->oempage.value); - oemcp->oempage.value = 0; -#ifndef _KERNEL - (void) mutex_unlock(&mutex); -#endif /* _KERNEL */ - return (-1); - } - - /* - * The default English page is stored in kernel. - * Therefore, no need to go to codepage files. - */ -#ifndef _KERNEL - if (cpid == oem_default_smb_cpid) - default_oem_cp = oem_default_smb_cp; - else if (cpid == oem_default_telnet_cpid) - default_oem_cp = oem_default_telnet_cp; - else - default_oem_cp = 0; -#else /* _KERNEL */ - default_oem_cp = oem_default_smb_cp; -#endif /* _KERNEL */ - - if (default_oem_cp) { - int i; - - for (i = 0; i < max_oem_index; i++) { - oemcp->oempage.value[i] = default_oem_cp[i]; - oemcp->unicodepage.value[default_oem_cp[i]] = - (mts_wchar_t)i; - } -#ifdef _KERNEL - } - /* - * XXX This doesn't seem right. How do we handle the situation - * where default_oem_cp == 0 in the kernel? - * Is this a PBSHORTCUT? - */ -#else - } else { - - /* - * The codepage is not one of the default that stores - * in the include - * file; therefore, we need to read from the file. - */ - (void) snprintf(filePath, sizeof (filePath), - "%s/%s", codepagePath, oemcp->filename); - fp = fopen(filePath, "r"); - - if (fp == 0) { - MEM_FREE("oem", oemcp->oempage.value); - MEM_FREE("oem", oemcp->unicodepage.value); -#ifndef _KERNEL - (void) mutex_unlock(&mutex); -#endif /* _KERNEL */ - return (-1); - } - - while (fgets(buf, 32, fp) != 0) { - char *endptr; - unsigned int oemval, unival; - - endptr = (char *)strchr(buf, ' '); - if (endptr == 0) { - continue; - } - - oemval = strtol(buf, &endptr, 0); - unival = strtol(endptr+1, 0, 0); - - if (oemval >= max_oem_index || unival >= MAX_UNI_IDX) { - continue; - } - - oemcp->oempage.value[oemval] = unival; - oemcp->unicodepage.value[unival] = oemval; - } - (void) fclose(fp); - } -#endif /* _KERNEL */ - - oemcp->valid = 1; -#ifndef _KERNEL - (void) mutex_unlock(&mutex); -#endif /* _KERNEL */ - return (0); -} - - - - -/* - * oem_codepage_free - * - * This function will clear the valid bit and free the memory - * allocated to the oem/unipage by oem_codepage_init if the ref count - * is zero. - */ -void -oem_codepage_free(unsigned int cpid) -{ - oem_codepage_t *oemcp; - - if (cpid >= MAX_OEMPAGES || !oemcp_table[cpid].valid) - return; - - oemcp = &oemcp_table[cpid]; - oemcp->valid--; - - if (oemcp->ref != 0 || oemcp->valid != 0) - return; - - if (oemcp->oempage.value != 0) { - MEM_FREE("oem", oemcp->oempage.value); - oemcp->oempage.value = 0; - } - - if (oemcp->unicodepage.value != 0) { - MEM_FREE("oem", oemcp->unicodepage.value); - oemcp->unicodepage.value = 0; - } -} - - - -/* - * oem_get_oempage - * - * This function will return the current oempage and increment - * the ref count. The function oem_release_page should always - * be called when finish using the oempage to decrement the - * ref count. - */ -static oempage_t * -oem_get_oempage(unsigned int cpid) -{ - if (cpid >= MAX_OEMPAGES) - return (0); - - if (oemcp_table[cpid].valid) { - oemcp_table[cpid].ref++; - return (&oemcp_table[cpid].oempage); - } - return (0); -} - - - -/* - * oem_get_unipage - * - * This function will return the current unipage and increment - * the ref count. The function oem_release_page should always - * be called when finish using the unipage to decrement the - * ref count. - */ -static oempage_t * -oem_get_unipage(unsigned int cpid) -{ - if (cpid >= MAX_OEMPAGES) - return (0); - - if (oemcp_table[cpid].valid) { - oemcp_table[cpid].ref++; - return (&oemcp_table[cpid].unicodepage); - } - return (0); -} - - - -/* - * oem_release_page - * - * This function will decrement the ref count and check the valid - * bit. It will free the memory allocated for the pages - * if the - * valid bit is not set, ref count is zero and the page is not - * already freed. - */ -static void -oem_release_page(oempage_t *page) -{ - oem_codepage_t *oemcp = &oemcp_table[page->cpid]; - - page = 0; - - if (oemcp->ref > 0) - oemcp->ref--; - - if (oemcp->ref != 0 || oemcp->valid) - return; - - if (oemcp->oempage.value != 0) { - MEM_FREE("oem", oemcp->oempage.value); - oemcp->oempage.value = 0; - } - - if (oemcp->unicodepage.value != 0) { - MEM_FREE("oem", oemcp->unicodepage.value); - oemcp->unicodepage.value = 0; - } -} - - - -/* - * unicodestooems - * - * Convert unicode string to oem string. The function will stop - * converting the unicode string when size nbytes - 1 is reached - * or when there is not enough room to store another unicode. - * If the function is called when the codepage is not initialized - * or when the codepage initialize failed, it will return 0. - * Otherwise, the total # of the converted unicode is returned. + * The number of converted unicode characters is returned, + * or 0 on error. */ size_t -unicodestooems( - char *oemstring, - const mts_wchar_t *unicodestring, - size_t nbytes, - unsigned int cpid) +ucstooem(char *oem, const smb_wchar_t *ucs, size_t nbytes, uint32_t cpid) { - oempage_t *unipage; - unsigned int count = 0; - mts_wchar_t oemchar; - - if (cpid >= MAX_OEMPAGES) - return (0); + oempage_t *ucspage; + uint32_t count = 0; + smb_wchar_t oemchar; - if (unicodestring == 0 || oemstring == 0) + if (ucs == NULL || oem == NULL) return (0); - if ((unipage = oem_get_unipage(cpid)) == 0) + if ((ucspage = oem_get_ucspage(cpid)) == NULL) return (0); - while ((oemchar = unipage->value[*unicodestring]) != 0) { + while (nbytes != 0 && (oemchar = ucspage->value[*ucs]) != 0) { if (oemchar & 0xff00 && nbytes >= MTS_MB_CHAR_MAX) { - *oemstring++ = oemchar >> 8; - *oemstring++ = (char)oemchar; + *oem++ = oemchar >> 8; + *oem++ = (char)oemchar; nbytes -= 2; } else if (nbytes > 1) { - *oemstring++ = (char)oemchar; + *oem++ = (char)oemchar; nbytes--; - } else + } else { break; + } count++; - unicodestring++; + ucs++; } - *oemstring = 0; - - oem_release_page(unipage); - + *oem = '\0'; return (count); } - - /* - * oemstounicodes + * Convert an oem string to a unicode string. * - * Convert oem string to unicode string. The function will stop - * converting the oem string when unicodestring len reaches nwchars - 1. - * or when there is not enough room to store another oem char. - * If the function is called when the codepage is not initialized - * or when the codepage initialize failed, it will return 0. - * Otherwise, the total # of the converted oem chars is returned. - * The oem char can be either 1 or 2 bytes. + * The conversion will stop at the end of the oem string or + * when nwchars - 1 have been converted. + * + * The number of converted oem chars is returned, or 0 on error. + * An oem char may be either 1 or 2 bytes. */ size_t -oemstounicodes( - mts_wchar_t *unicodestring, - const char *oemstring, - size_t nwchars, - unsigned int cpid) +oemtoucs(smb_wchar_t *ucs, const char *oem, size_t nwchars, uint32_t cpid) { - oempage_t *oempage; - size_t count = nwchars; - mts_wchar_t oemchar; + oempage_t *oempage; + size_t count = nwchars; + smb_wchar_t oemchar; - if (cpid >= MAX_OEMPAGES) + if (ucs == NULL || oem == NULL) return (0); - if (unicodestring == 0 || oemstring == 0) + if ((oempage = oem_get_oempage(cpid)) == NULL) return (0); - if ((oempage = oem_get_oempage(cpid)) == 0) - return (0); - - while ((oemchar = (mts_wchar_t)*oemstring++ & 0xff) != 0) { + while ((oemchar = (smb_wchar_t)*oem++ & 0xff) != 0) { /* - * Cannot find one byte oemchar in table. Must be - * a lead byte. Try two bytes. + * Cannot find one byte oemchar in table. + * Must be a lead byte. Try two bytes. */ - if ((oempage->value[oemchar] == 0) && (oemchar != 0)) { - oemchar = oemchar << 8 | (*oemstring++ & 0xff); + oemchar = oemchar << 8 | (*oem++ & 0xff); if (oempage->value[oemchar] == 0) { - *unicodestring = 0; + *ucs = 0; break; } } #ifdef _BIG_ENDIAN - *unicodestring = LE_IN16(&oempage->value[oemchar]); + *ucs = LE_IN16(&oempage->value[oemchar]); #else - *unicodestring = oempage->value[oemchar]; + *ucs = oempage->value[oemchar]; #endif count--; - unicodestring++; + ucs++; } - *unicodestring = 0; - - oem_release_page(oempage); - + *ucs = 0; return (nwchars - count); } /* - * oem_get_lang_table - * - * This function returns a pointer to the language table. + * Get a pointer to the oem page for the specific codepage id. */ -language * -oem_get_lang_table(void) +static oempage_t * +oem_get_oempage(uint32_t cpid) { - return (lang_table); + if (cpid >= MAX_OEMPAGES) + return (NULL); + + if (!oemcpg_table[cpid].valid) { + oem_codepage_init(cpid); + + if (!oemcpg_table[cpid].valid) + return (NULL); + } + + return (&oemcpg_table[cpid].oempage); } /* - * oem_no_of_languages - * - * This function returns total languages support in the system. + * Get a pointer to the ucs page for the specific codepage id. */ -int -oem_no_of_languages(void) +static oempage_t * +oem_get_ucspage(uint32_t cpid) { - return (sizeof (lang_table)/sizeof (lang_table[0])); -} + if (cpid >= MAX_OEMPAGES) + return (NULL); + if (!oemcpg_table[cpid].valid) { + oem_codepage_init(cpid); + + if (!oemcpg_table[cpid].valid) + return (NULL); + } + + return (&oemcpg_table[cpid].ucspage); +} -#ifndef _KERNEL -#if 1 /* - * TESTING Functions + * Initialize the oem page in the oem table. */ -void -oemcp_print(unsigned int cpid) +static void +oem_codepage_init(uint32_t cpid) { - unsigned int bytesperchar, max_index, i; - oempage_t *oempage, *unipage; - unsigned int counter = 0; +#ifndef _KERNEL + static mutex_t mutex; - if (cpid >= MAX_OEMPAGES) { - (void) printf("oemcp cpid %d is invalid\n", cpid); - return; - } + (void) mutex_lock(&mutex); + oem_codepage_setup(cpid); + (void) mutex_unlock(&mutex); +#else + static kmutex_t mutex; - if ((oempage = oem_get_oempage(cpid)) == 0) { - (void) printf("oemcp of cpid %d is invalid\n", cpid); - return; - } + mutex_enter(&mutex); + oem_codepage_setup(cpid); + mutex_exit(&mutex); +#endif /* _KERNEL */ +} - if ((unipage = oem_get_unipage(cpid)) == 0) { - (void) printf("unicp of cpid %d is invalid\n", cpid); +static void +oem_codepage_setup(uint32_t cpid) +{ + smb_wchar_t *default_oem_cp; + oem_codepage_t *oemcpg; + uint32_t bytesperchar; + uint32_t max_oem_index; + int i; + + switch (cpid) { + case OEM_CPG_850: + default_oem_cp = oem_codepage_850; + break; + case OEM_CPG_1252: + default_oem_cp = oem_codepage_1252; + default: return; } - if ((bytesperchar = oem_codepage_bytesperchar(cpid)) == 0) { - (void) printf("bytesperchar of cpid %d is not correct\n", cpid); + oemcpg = &oemcpg_table[cpid]; + if (oemcpg->valid) return; - } - - max_index = 1 << bytesperchar * 8; - - (void) printf("OEMPAGE:\n"); - for (i = 0; i < max_index; i++) { - if ((counter + 1) % 4 == 0 && - (oempage->value[i] != 0 || i == 0)) { - (void) printf("%x %x\n", i, oempage->value[i]); - counter++; - } else if (oempage->value[i] != 0 || i == 0) { - (void) printf("%x %x, ", i, oempage->value[i]); - counter++; - } - } - counter = 0; - (void) printf("\n\nUNIPAGE:\n"); - for (i = 0; i < 65536; i++) { - if ((counter + 1) % 8 == 0 && - (unipage->value[i] != 0 || i == 0)) { - (void) printf("%x %x\n", i, unipage->value[i]); - counter++; - } else if (unipage->value[i] != 0 || i == 0) { - (void) printf("%x %x, ", i, unipage->value[i]); - counter++; - } - } - (void) printf("\n"); - oem_release_page(oempage); - oem_release_page(unipage); -} - - - -void -oemstringtest(unsigned int cpid) -{ - unsigned char *c, *cbuf; - unsigned char cbuf1[100] = {0xfe, 0xfd, 0xf2, 0xe9, - 0x63, 0xce, 0xdb, 0x8c, 0x9c, 0x21, 0}; - unsigned char cbuf2[100] = {0xfe, 0xfc, 0x63, 0x81, 0x42, - 0x91, 0x40, 0x24, 0xff, 0x49}; - mts_wchar_t buf[100], *wc; - - if (cpid == 1) - cbuf = cbuf1; - else if (cpid == 2) - cbuf = cbuf2; /* - * Before oem->uni conversion. + * max_oem_index will be 256 or 65536 dependent + * on the OEM codepage. */ - (void) printf("Before oem->uni conversion: "); - for (c = cbuf; *c != 0; c++) - (void) printf("%x ", *c); - (void) printf("\n"); + bytesperchar = oemcpg_table[cpid].bytesperchar; + max_oem_index = 1 << (bytesperchar * 8); - /* - * oem->uni conversion - */ - (void) oemstounicodes(buf, (const char *)cbuf, 100, cpid); + oemcpg->oempage.value = + MEM_ZALLOC("oem", max_oem_index * sizeof (smb_wchar_t)); + if (oemcpg->oempage.value == NULL) + return; - /* - * After oem->uni conversion. - */ - (void) printf("After oem->uni conversion: "); - for (wc = buf; *wc != 0; wc++) - (void) printf("%x ", *wc); - (void) printf("\n"); + oemcpg->ucspage.value = + MEM_ZALLOC("oem", MAX_UNICODE_IDX * sizeof (smb_wchar_t)); + if (oemcpg->ucspage.value == NULL) { + MEM_FREE("oem", oemcpg->oempage.value); + oemcpg->oempage.value = NULL; + return; + } - /* - * uni->oem conversion - */ - (void) unicodestooems((char *)cbuf, buf, 100, cpid); + for (i = 0; i < max_oem_index; i++) { + oemcpg->oempage.value[i] = default_oem_cp[i]; + oemcpg->ucspage.value[default_oem_cp[i]] = (smb_wchar_t)i; + } - /* - * After uni->oem conversion. - */ - (void) printf("After uni->oem conversion: "); - for (c = cbuf; *c != 0; c++) - (void) printf("%x ", *c); - (void) printf("\n"); + oemcpg->valid = B_TRUE; } -#endif -#endif /* _KERNEL */ diff --git a/usr/src/common/smbsrv/smb_opmlang.c b/usr/src/common/smbsrv/smb_opmlang.c deleted file mode 100644 index af7ee73cb1..0000000000 --- a/usr/src/common/smbsrv/smb_opmlang.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <smbsrv/string.h> -#include <smbsrv/codepage.h> -#include <smbsrv/oem.h> - -static unsigned int smb_cpid = NO_OF_OEM_CP_INDS; -static unsigned int telnet_cpid = NO_OF_OEM_CP_INDS; - -/* - * oem_get_smb_cpid - * - * This function returns the cpid for current smb codepage. - */ -unsigned int -oem_get_smb_cpid(void) -{ - return (smb_cpid); -} - -/* - * oem_get_telnet_cpid - * - * This function returns the cpid for current telnet codepage. - */ -unsigned int -oem_get_telnet_cpid(void) -{ - return (telnet_cpid); -} - -/* - * oem_current_language - * - * This function will return the current language setting. - * The current language is stored in env "codepage.oem.language". - * If the env does not exist, "None Selected" will be returned. - */ -char * -oem_current_language() -{ -#ifdef PBSHORTCUT - char *p = getenv("codepage.oem.language"); - - if (p) - return (p); -#endif - return ("None Selected"); -} - - -/* - * oem_language_set - * - * This function will set the oem language and correct - * env variables. - */ -int -oem_language_set(char *lang_name) -{ - int i; - language *lang_table = oem_get_lang_table(); - - for (i = 0; i < NO_OF_LANGUAGES; i++) { - if (utf8_strcasecmp(lang_name, lang_table[i].language) == 0) { - unsigned int oldSmbIndex = smb_cpid; - unsigned int oldTelnetIndex = telnet_cpid; - if (oem_codepage_init(lang_table[i].smbIndex) < 0 || - oem_codepage_init(lang_table[i].telnetIndex) < 0) { - oem_codepage_free(lang_table[i].smbIndex); - oem_codepage_free(lang_table[i].telnetIndex); - (void) oem_codepage_init(oem_default_smb_cpid); - (void) oem_codepage_init( - oem_default_telnet_cpid); - smb_cpid = oem_default_smb_cpid; - telnet_cpid = oem_default_telnet_cpid; -#ifdef PBSHORTCUT - setenv("codepage.oem.language", - oem_default_language); -#endif - } else { - smb_cpid = lang_table[i].smbIndex; - telnet_cpid = lang_table[i].telnetIndex; -#ifdef PBSHORTCUT - setenv("codepage.oem.language", - lang_table[i].language); -#endif - } -#ifdef PBSHORTCUT - saveenv(); -#endif - - if (oldSmbIndex < NO_OF_OEM_CP_INDS) - oem_codepage_free(oldSmbIndex); - if (oldTelnetIndex < NO_OF_OEM_CP_INDS) - oem_codepage_free(oldTelnetIndex); - return (0); - } - } - - return (-1); -} diff --git a/usr/src/common/smbsrv/smb_strcase.c b/usr/src/common/smbsrv/smb_strcase.c deleted file mode 100644 index e1de2cdd32..0000000000 --- a/usr/src/common/smbsrv/smb_strcase.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - -/* - * Case conversion functions for strings. Originally this module only - * dealt with ASCII strings. It has been updated to support European - * character set characters. The current implementation is based on - * code page table lookup rather than simple character range checks. - */ - -#ifdef _KERNEL -#include <sys/types.h> -#include <sys/sunddi.h> -#else -#include <stdio.h> -#include <string.h> -#endif -#include <smbsrv/ctype.h> -#include <smbsrv/codepage.h> -#include <smbsrv/cp_cyrillic.h> -#include <smbsrv/cp_latin1.h> -#include <smbsrv/cp_latin2.h> -#include <smbsrv/cp_latin3.h> -#include <smbsrv/cp_latin4.h> -#include <smbsrv/cp_latin5.h> -#include <smbsrv/cp_latin6.h> -#include <smbsrv/cp_usascii.h> - -/* - * Global pointer to the current code page. This is - * defaulted to a standard ASCII table. - */ -static codepage_t *current_codepage = usascii_codepage; - -/* - * A flag indicating whether the codepage being used is ASCII - * When this flag is set, string opeartions can go faster. - */ -static int is_unicode = 0; - -/* - * codepage_isupper - * - * Determine whether or not a character is an uppercase character. - * This function operates on the current codepage table. Returns - * non-zero if the character is uppercase. Otherwise returns zero. - */ -int -codepage_isupper(int c) -{ - unsigned short mask = is_unicode ? 0xffff : 0xff; - - return (current_codepage[c & mask].ctype & CODEPAGE_ISUPPER); -} - - -/* - * codepage_islower - * - * Determine whether or not a character is an lowercase character. - * This function operates on the current codepage table. Returns - * non-zero if the character is lowercase. Otherwise returns zero. - */ -int -codepage_islower(int c) -{ - unsigned short mask = is_unicode ? 0xffff : 0xff; - - return (current_codepage[c & mask].ctype & CODEPAGE_ISLOWER); -} - - -/* - * codepage_toupper - * - * Convert individual characters to their uppercase equivalent value. - * If the specified character is lowercase, the uppercase value will - * be returned. Otherwise the original value will be returned. - */ -int -codepage_toupper(int c) -{ - unsigned short mask = is_unicode ? 0xffff : 0xff; - - return (current_codepage[c & mask].upper); -} - - -/* - * codepage_tolower - * - * Convert individual characters to their lowercase equivalent value. - * If the specified character is uppercase, the lowercase value will - * be returned. Otherwise the original value will be returned. - */ -int -codepage_tolower(int c) -{ - unsigned short mask = is_unicode ? 0xffff : 0xff; - - return (current_codepage[c & mask].lower); -} - - -/* - * strupr - * - * Convert a string to uppercase using the appropriate codepage. The - * string is converted in place. A pointer to the string is returned. - * There is an assumption here that uppercase and lowercase values - * always result encode to the same length. - */ -char * -utf8_strupr(char *s) -{ - mts_wchar_t c; - char *p = s; - - while (*p) { - if (mts_isascii(*p)) { - *p = codepage_toupper(*p); - p++; - } else { - if (mts_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0) - return (0); - - if (c == 0) - break; - - c = codepage_toupper(c); - p += mts_wctomb(p, c); - } - } - - return (s); -} - - -/* - * strlwr - * - * Convert a string to lowercase using the appropriate codepage. The - * string is converted in place. A pointer to the string is returned. - * There is an assumption here that uppercase and lowercase values - * always result encode to the same length. - */ -char * -utf8_strlwr(char *s) -{ - mts_wchar_t c; - char *p = s; - - while (*p) { - if (mts_isascii(*p)) { - *p = codepage_tolower(*p); - p++; - } else { - if (mts_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0) - return (0); - - if (c == 0) - break; - - c = codepage_tolower(c); - p += mts_wctomb(p, c); - } - } - - return (s); -} - - -/* - * isstrlwr - * - * Returns 1 if string contains NO uppercase chars 0 otherwise. However, - * -1 is returned if "s" is not a valid multi-byte string. - */ -int -utf8_isstrlwr(const char *s) -{ - mts_wchar_t c; - int n; - const char *p = s; - - while (*p) { - if (mts_isascii(*p) && codepage_isupper(*p)) - return (0); - else { - if ((n = mts_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0) - return (-1); - - if (c == 0) - break; - - if (codepage_isupper(c)) - return (0); - - p += n; - } - } - - return (1); -} - - -/* - * isstrupr - * - * Returns 1 if string contains NO lowercase chars 0 otherwise. However, - * -1 is returned if "s" is not a valid multi-byte string. - */ -int -utf8_isstrupr(const char *s) -{ - mts_wchar_t c; - int n; - const char *p = s; - - while (*p) { - if (mts_isascii(*p) && codepage_islower(*p)) - return (0); - else { - if ((n = mts_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0) - return (-1); - - if (c == 0) - break; - - if (codepage_islower(c)) - return (0); - - p += n; - } - } - - return (1); -} - - -/* - * strcasecmp - * - * Compare the null-terminated strings s1 and s2 and return an integer - * greater than, equal to, or less than 0, according as s1 is lexico - * graphically greater than, equal to, or less than s2 after translation - * of each corresponding character to lowercase. The strings themselves - * are not modified. - * - * Out: 0 if strings are equal - * < 0 if first string < second string - * > 0 if first string > second string - */ -int -utf8_strcasecmp(const char *s1, const char *s2) -{ - mts_wchar_t c1, c2; - int n1, n2; - const char *p1 = s1; - const char *p2 = s2; - - for (;;) { - if (mts_isascii(*p1)) - c1 = *p1++; - else { - if ((n1 = mts_mbtowc(&c1, p1, MTS_MB_CHAR_MAX)) < 0) - return (-1); - p1 += n1; - } - - if (mts_isascii(*p2)) - c2 = *p2++; - else { - if ((n2 = mts_mbtowc(&c2, p2, MTS_MB_CHAR_MAX)) < 0) - return (1); - p2 += n2; - } - - if (c1 == 0 || c2 == 0) - break; - - if (c1 == c2) - continue; - - c1 = codepage_tolower(c1); - c2 = codepage_tolower(c2); - - if (c1 != c2) - break; - } - - return ((int)c1 - (int)c2); -} - - -/* - * strncasecmp - * - * Compare two null-terminated strings, s1 and s2, of at most len - * characters and return an int greater than, equal to, or less than 0, - * dependent on whether s1 is lexicographically greater than, equal to, - * or less than s2 after translation of each corresponding character to - * lowercase. The original strings are not modified. - * - * Out: 0 if strings are equal - * < 0 if first string < second string - * > 0 if first string > second string - */ -int -utf8_strncasecmp(const char *s1, const char *s2, int len) -{ - mts_wchar_t c1, c2; - int n1, n2; - const char *p1 = s1; - const char *p2 = s2; - - if (len <= 0) - return (0); - - while (len--) { - if (mts_isascii(*p1)) - c1 = *p1++; - else { - if ((n1 = mts_mbtowc(&c1, p1, MTS_MB_CHAR_MAX)) < 0) - return (-1); - p1 += n1; - } - - if (mts_isascii(*p2)) - c2 = *p2++; - else { - if ((n2 = mts_mbtowc(&c2, p2, MTS_MB_CHAR_MAX)) < 0) - return (1); - p2 += n2; - } - - if (c1 == 0 || c2 == 0) - break; - - if (c1 == c2) - continue; - - c1 = codepage_tolower(c1); - c2 = codepage_tolower(c2); - - if (c1 != c2) - break; - } - - return ((int)c1 - (int)c2); -} - - - -int -utf8_isstrascii(const char *s) -{ - while (*s) { - if (mts_isascii(*s) == 0) - return (0); - s++; - } - return (1); -} diff --git a/usr/src/common/smbsrv/smb_string.c b/usr/src/common/smbsrv/smb_string.c index 8133f72ceb..292f58d4fa 100644 --- a/usr/src/common/smbsrv/smb_string.c +++ b/usr/src/common/smbsrv/smb_string.c @@ -19,27 +19,35 @@ * CDDL HEADER END */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -/* - * Implementation of some of the string functions. - */ - -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef _KERNEL #include <sys/types.h> #include <sys/sunddi.h> #else +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> #endif +#include <sys/u8_textprep.h> +#include <smbsrv/alloc.h> #include <smbsrv/string.h> -#include <smbsrv/ctype.h> +#include <smbsrv/cp_usascii.h> +#include <smbsrv/cp_unicode.h> + +#define UNICODE_N_ENTRIES (sizeof (a_unicode) / sizeof (a_unicode[0])) + +/* + * Global pointer to the current codepage: defaults to ASCII, + * and a flag indicating whether the codepage is Unicode or ASCII. + */ +static smb_codepage_t *current_codepage = usascii_codepage; +static boolean_t is_unicode = B_FALSE; +static smb_codepage_t *smb_unicode_init(void); /* * strsubst @@ -100,3 +108,305 @@ strcanon(char *buf, const char *class) *q = '\0'; return (buf); } + +void +smb_codepage_init(void) +{ + smb_codepage_t *cp; + + if (is_unicode) + return; + + if ((cp = smb_unicode_init()) != NULL) { + current_codepage = cp; + is_unicode = B_TRUE; + } else { + current_codepage = usascii_codepage; + is_unicode = B_FALSE; + } +} + +/* + * Determine whether or not a character is an uppercase character. + * This function operates on the current codepage table. Returns + * non-zero if the character is uppercase. Otherwise returns zero. + */ +int +smb_isupper(int c) +{ + uint16_t mask = is_unicode ? 0xffff : 0xff; + + return (current_codepage[c & mask].ctype & CODEPAGE_ISUPPER); +} + +/* + * Determine whether or not a character is an lowercase character. + * This function operates on the current codepage table. Returns + * non-zero if the character is lowercase. Otherwise returns zero. + */ +int +smb_islower(int c) +{ + uint16_t mask = is_unicode ? 0xffff : 0xff; + + return (current_codepage[c & mask].ctype & CODEPAGE_ISLOWER); +} + +/* + * Convert individual characters to their uppercase equivalent value. + * If the specified character is lowercase, the uppercase value will + * be returned. Otherwise the original value will be returned. + */ +int +smb_toupper(int c) +{ + uint16_t mask = is_unicode ? 0xffff : 0xff; + + return (current_codepage[c & mask].upper); +} + +/* + * Convert individual characters to their lowercase equivalent value. + * If the specified character is uppercase, the lowercase value will + * be returned. Otherwise the original value will be returned. + */ +int +smb_tolower(int c) +{ + uint16_t mask = is_unicode ? 0xffff : 0xff; + + return (current_codepage[c & mask].lower); +} + +/* + * Convert a string to uppercase using the appropriate codepage. The + * string is converted in place. A pointer to the string is returned. + * There is an assumption here that uppercase and lowercase values + * always result encode to the same length. + */ +char * +smb_strupr(char *s) +{ + smb_wchar_t c; + char *p = s; + + while (*p) { + if (smb_isascii(*p)) { + *p = smb_toupper(*p); + p++; + } else { + if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0) + return (0); + + if (c == 0) + break; + + c = smb_toupper(c); + p += smb_wctomb(p, c); + } + } + + return (s); +} + +/* + * Convert a string to lowercase using the appropriate codepage. The + * string is converted in place. A pointer to the string is returned. + * There is an assumption here that uppercase and lowercase values + * always result encode to the same length. + */ +char * +smb_strlwr(char *s) +{ + smb_wchar_t c; + char *p = s; + + while (*p) { + if (smb_isascii(*p)) { + *p = smb_tolower(*p); + p++; + } else { + if (smb_mbtowc(&c, p, MTS_MB_CHAR_MAX) < 0) + return (0); + + if (c == 0) + break; + + c = smb_tolower(c); + p += smb_wctomb(p, c); + } + } + + return (s); +} + +/* + * Returns 1 if string contains NO uppercase chars 0 otherwise. However, + * -1 is returned if "s" is not a valid multi-byte string. + */ +int +smb_isstrlwr(const char *s) +{ + smb_wchar_t c; + int n; + const char *p = s; + + while (*p) { + if (smb_isascii(*p) && smb_isupper(*p)) + return (0); + else { + if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0) + return (-1); + + if (c == 0) + break; + + if (smb_isupper(c)) + return (0); + + p += n; + } + } + + return (1); +} + +/* + * Returns 1 if string contains NO lowercase chars 0 otherwise. However, + * -1 is returned if "s" is not a valid multi-byte string. + */ +int +smb_isstrupr(const char *s) +{ + smb_wchar_t c; + int n; + const char *p = s; + + while (*p) { + if (smb_isascii(*p) && smb_islower(*p)) + return (0); + else { + if ((n = smb_mbtowc(&c, p, MTS_MB_CHAR_MAX)) < 0) + return (-1); + + if (c == 0) + break; + + if (smb_islower(c)) + return (0); + + p += n; + } + } + + return (1); +} + +/* + * Compare the null-terminated strings s1 and s2 and return an integer + * greater than, equal to or less than 0 dependent on whether s1 is + * lexicographically greater than, equal to or less than s2 after + * translation of each character to lowercase. The original strings + * are not modified. + * + * If n is non-zero, at most n bytes are compared. Otherwise, the strings + * are compared until a null terminator is encountered. + * + * Out: 0 if strings are equal + * < 0 if first string < second string + * > 0 if first string > second string + */ +int +smb_strcasecmp(const char *s1, const char *s2, size_t n) +{ + int err = 0; + int rc; + + rc = u8_strcmp(s1, s2, n, U8_STRCMP_CI_LOWER, U8_UNICODE_LATEST, &err); + if (err != 0) + return (-1); + return (rc); +} + +/* + * First build a codepage based on cp_unicode.h. Then build the unicode + * codepage from this interim codepage by copying the entries over while + * fixing them and filling in the gaps. + */ +static smb_codepage_t * +smb_unicode_init(void) +{ + smb_codepage_t *unicode; + uint32_t a = 0; + uint32_t b = 0; + + unicode = MEM_ZALLOC("unicode", sizeof (smb_codepage_t) << 16); + if (unicode == NULL) + return (NULL); + + while (b != 0xffff) { + /* + * If there is a gap in the standard, + * fill in the gap with no-case entries. + */ + if (UNICODE_N_ENTRIES <= a || a_unicode[a].val > b) { + unicode[b].ctype = CODEPAGE_ISNONE; + unicode[b].upper = (smb_wchar_t)b; + unicode[b].lower = (smb_wchar_t)b; + b++; + continue; + } + + /* + * Copy the entry and fixup as required. + */ + switch (a_unicode[a].ctype) { + case CODEPAGE_ISNONE: + /* + * Replace 0xffff in upper/lower fields with its val. + */ + unicode[b].ctype = CODEPAGE_ISNONE; + unicode[b].upper = (smb_wchar_t)b; + unicode[b].lower = (smb_wchar_t)b; + break; + case CODEPAGE_ISUPPER: + /* + * Some characters may have case yet not have + * case conversion. Treat them as no-case. + */ + if (a_unicode[a].lower == 0xffff) { + unicode[b].ctype = CODEPAGE_ISNONE; + unicode[b].upper = (smb_wchar_t)b; + unicode[b].lower = (smb_wchar_t)b; + } else { + unicode[b].ctype = CODEPAGE_ISUPPER; + unicode[b].upper = (smb_wchar_t)b; + unicode[b].lower = a_unicode[a].lower; + } + break; + case CODEPAGE_ISLOWER: + /* + * Some characters may have case yet not have + * case conversion. Treat them as no-case. + */ + if (a_unicode[a].upper == 0xffff) { + unicode[b].ctype = CODEPAGE_ISNONE; + unicode[b].upper = (smb_wchar_t)b; + unicode[b].lower = (smb_wchar_t)b; + } else { + unicode[b].ctype = CODEPAGE_ISLOWER; + unicode[b].upper = a_unicode[a].upper; + unicode[b].lower = (smb_wchar_t)b; + } + break; + default: + MEM_FREE("unicode", unicode); + return (NULL); + } + + a++; + b++; + }; + + return (unicode); +} diff --git a/usr/src/common/smbsrv/smb_utf8.c b/usr/src/common/smbsrv/smb_utf8.c index 4cdc44bee1..a328e32f7b 100644 --- a/usr/src/common/smbsrv/smb_utf8.c +++ b/usr/src/common/smbsrv/smb_utf8.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,8 +48,6 @@ * October 1996 */ -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef _KERNEL #include <sys/types.h> #include <sys/sunddi.h> @@ -59,7 +57,6 @@ #include <assert.h> #include <strings.h> #endif -#include <smbsrv/smb_i18n.h> #include <smbsrv/string.h> @@ -76,13 +73,13 @@ * multibyte character is encountered. */ size_t -mts_mbstowcs(mts_wchar_t *wcstring, const char *mbstring, size_t nwchars) +smb_mbstowcs(smb_wchar_t *wcstring, const char *mbstring, size_t nwchars) { int len; - mts_wchar_t *start = wcstring; + smb_wchar_t *start = wcstring; while (nwchars--) { - len = mts_mbtowc(wcstring, mbstring, MTS_MB_CHAR_MAX); + len = smb_mbtowc(wcstring, mbstring, MTS_MB_CHAR_MAX); if (len < 0) { *wcstring = 0; return ((size_t)-1); @@ -117,10 +114,10 @@ mts_mbstowcs(mts_wchar_t *wcstring, const char *mbstring, size_t nwchars) * mbchar. If mbchar is invalid, returns -1. */ int /*ARGSUSED*/ -mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) +smb_mbtowc(smb_wchar_t *wcharp, const char *mbchar, size_t nbytes) { unsigned char mbyte; - mts_wchar_t wide_char; + smb_wchar_t wide_char; int count; int bytes_left; @@ -130,7 +127,7 @@ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) /* 0xxxxxxx -> 1 byte ASCII encoding */ if (((mbyte = *mbchar++) & 0x80) == 0) { if (wcharp) - *wcharp = (mts_wchar_t)mbyte; + *wcharp = (smb_wchar_t)mbyte; return (mbyte ? 1 : 0); } @@ -176,7 +173,7 @@ mts_mbtowc(mts_wchar_t *wcharp, const char *mbchar, size_t nbytes) * Returns the numberof bytes written to mbchar. */ int -mts_wctomb(char *mbchar, mts_wchar_t wchar) +smb_wctomb(char *mbchar, smb_wchar_t wchar) { if ((wchar & ~0x7f) == 0) { *mbchar = (char)wchar; @@ -209,11 +206,11 @@ mts_wctomb(char *mbchar, mts_wchar_t wchar) * null byte. */ size_t -mts_wcstombs(char *mbstring, const mts_wchar_t *wcstring, size_t nbytes) +smb_wcstombs(char *mbstring, const smb_wchar_t *wcstring, size_t nbytes) { char *start = mbstring; - const mts_wchar_t *wcp = wcstring; - mts_wchar_t wide_char; + const smb_wchar_t *wcp = wcstring; + smb_wchar_t wide_char; char buf[4]; size_t len; @@ -222,7 +219,7 @@ mts_wcstombs(char *mbstring, const mts_wchar_t *wcstring, size_t nbytes) while (nbytes > MTS_MB_CHAR_MAX) { wide_char = *wcp++; - len = mts_wctomb(mbstring, wide_char); + len = smb_wctomb(mbstring, wide_char); if (wide_char == 0) /*LINTED E_PTRDIFF_OVERFLOW*/ @@ -234,7 +231,7 @@ mts_wcstombs(char *mbstring, const mts_wchar_t *wcstring, size_t nbytes) while (wide_char && nbytes) { wide_char = *wcp++; - if ((len = mts_wctomb(buf, wide_char)) > nbytes) { + if ((len = smb_wctomb(buf, wide_char)) > nbytes) { *mbstring = 0; break; } @@ -255,18 +252,18 @@ mts_wcstombs(char *mbstring, const mts_wchar_t *wcstring, size_t nbytes) * counting the terminating null wide character. */ size_t -mts_wcequiv_strlen(const char *mbs) +smb_wcequiv_strlen(const char *mbs) { - mts_wchar_t wide_char; + smb_wchar_t wide_char; size_t bytes; size_t len = 0; while (*mbs) { - bytes = mts_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); + bytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); if (bytes == ((size_t)-1)) return ((size_t)-1); - len += sizeof (mts_wchar_t); + len += sizeof (smb_wchar_t); mbs += bytes; } @@ -280,19 +277,19 @@ mts_wcequiv_strlen(const char *mbs) * not counting the terminating null character. */ size_t -mts_sbequiv_strlen(const char *mbs) +smb_sbequiv_strlen(const char *mbs) { - mts_wchar_t wide_char; + smb_wchar_t wide_char; size_t nbytes; size_t len = 0; while (*mbs) { - nbytes = mts_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); + nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); if (nbytes == ((size_t)-1)) return ((size_t)-1); if (wide_char & 0xFF00) - len += sizeof (mts_wchar_t); + len += sizeof (smb_wchar_t); else ++len; @@ -319,13 +316,13 @@ mts_sbequiv_strlen(const char *mbs) * If either mbstring or string is a null pointer, -1 is returned. */ int -mts_stombs(char *mbstring, char *string, int max_mblen) +smb_stombs(char *mbstring, char *string, int max_mblen) { char *start = mbstring; unsigned char *p = (unsigned char *)string; int space_left = max_mblen; int len; - mts_wchar_t wide_char; + smb_wchar_t wide_char; char buf[4]; if (!mbstring || !string) @@ -333,14 +330,14 @@ mts_stombs(char *mbstring, char *string, int max_mblen) while (*p && space_left > 2) { wide_char = *p++; - len = mts_wctomb(mbstring, wide_char); + len = smb_wctomb(mbstring, wide_char); mbstring += len; space_left -= len; } if (*p) { wide_char = *p; - if ((len = mts_wctomb(buf, wide_char)) < 2) { + if ((len = smb_wctomb(buf, wide_char)) < 2) { *mbstring = *buf; mbstring += len; space_left -= len; @@ -371,9 +368,9 @@ mts_stombs(char *mbstring, char *string, int max_mblen) * If either mbstring or string is a null pointer, -1 is returned. */ int -mts_mbstos(char *string, const char *mbstring) +smb_mbstos(char *string, const char *mbstring) { - mts_wchar_t wc; + smb_wchar_t wc; unsigned char *start = (unsigned char *)string; int len; @@ -381,15 +378,15 @@ mts_mbstos(char *string, const char *mbstring) return (-1); while (*mbstring) { - if ((len = mts_mbtowc(&wc, mbstring, MTS_MB_CHAR_MAX)) < 0) { + if ((len = smb_mbtowc(&wc, mbstring, MTS_MB_CHAR_MAX)) < 0) { *string = 0; return (-1); } if (wc & 0xFF00) { /*LINTED E_BAD_PTR_CAST_ALIGN*/ - *((mts_wchar_t *)string) = wc; - string += sizeof (mts_wchar_t); + *((smb_wchar_t *)string) = wc; + string += sizeof (smb_wchar_t); } else { |