1da6c28aaSamw /*
2da6c28aaSamw * CDDL HEADER START
3da6c28aaSamw *
4da6c28aaSamw * The contents of this file are subject to the terms of the
5da6c28aaSamw * Common Development and Distribution License (the "License").
6da6c28aaSamw * You may not use this file except in compliance with the License.
7da6c28aaSamw *
8da6c28aaSamw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9da6c28aaSamw * or http://www.opensolaris.org/os/licensing.
10da6c28aaSamw * See the License for the specific language governing permissions
11da6c28aaSamw * and limitations under the License.
12da6c28aaSamw *
13da6c28aaSamw * When distributing Covered Code, include this CDDL HEADER in each
14da6c28aaSamw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15da6c28aaSamw * If applicable, add the following below this CDDL HEADER, with the
16da6c28aaSamw * fields enclosed by brackets "[]" replaced with your own identifying
17da6c28aaSamw * information: Portions Copyright [yyyy] [name of copyright owner]
18da6c28aaSamw *
19da6c28aaSamw * CDDL HEADER END
20da6c28aaSamw */
21da6c28aaSamw /*
22bbf6f00cSJordan Brown * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23da6c28aaSamw * Use is subject to license terms.
24*b819cea2SGordon Ross *
25*b819cea2SGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26da6c28aaSamw */
27da6c28aaSamw
28da6c28aaSamw /*
29da6c28aaSamw * Support for oem <-> unicode translations.
30da6c28aaSamw */
31da6c28aaSamw
32*b819cea2SGordon Ross #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
33da6c28aaSamw #include <stdlib.h>
34da6c28aaSamw #include <thread.h>
35da6c28aaSamw #include <synch.h>
36da6c28aaSamw #include <string.h>
37bbf6f00cSJordan Brown #else
38bbf6f00cSJordan Brown #include <sys/ksynch.h>
39da6c28aaSamw #endif /* _KERNEL */
40bbf6f00cSJordan Brown
41bbf6f00cSJordan Brown #include <sys/byteorder.h>
42da6c28aaSamw #include <smbsrv/alloc.h>
43da6c28aaSamw #include <smbsrv/string.h>
44bbf6f00cSJordan Brown
45da6c28aaSamw /*
46bbf6f00cSJordan Brown * cpid The oemcpg_table index for this oempage.
47bbf6f00cSJordan Brown * value The conversion values.
48bbf6f00cSJordan Brown */
49bbf6f00cSJordan Brown typedef struct oempage {
50bbf6f00cSJordan Brown uint32_t cpid;
51bbf6f00cSJordan Brown smb_wchar_t *value;
52bbf6f00cSJordan Brown } oempage_t;
53bbf6f00cSJordan Brown
54bbf6f00cSJordan Brown /*
55bbf6f00cSJordan Brown * filename The actual filename contains the codepage.
56bbf6f00cSJordan Brown * bytesperchar The codepage uses double or single bytes per char.
57bbf6f00cSJordan Brown * oempage The oempage is used to convert Unicode characters to
58bbf6f00cSJordan Brown * OEM characters. Memory needs to be allocated for
59bbf6f00cSJordan Brown * the value field of oempage to store the table.
60bbf6f00cSJordan Brown * ucspage The unicode page is used to convert OEM characters
61bbf6f00cSJordan Brown * to Unicode characters. Memory needs to be allocated
62bbf6f00cSJordan Brown * for the value field of ucspage to store the table.
63bbf6f00cSJordan Brown * valid True if the codepage has been initialized.
64da6c28aaSamw */
65da6c28aaSamw typedef struct oem_codepage {
66bbf6f00cSJordan Brown char *filename;
67bbf6f00cSJordan Brown uint32_t bytesperchar;
68bbf6f00cSJordan Brown oempage_t oempage;
69bbf6f00cSJordan Brown oempage_t ucspage;
70bbf6f00cSJordan Brown boolean_t valid;
71da6c28aaSamw } oem_codepage_t;
72da6c28aaSamw
73bbf6f00cSJordan Brown static oem_codepage_t oemcpg_table[] = {
74bbf6f00cSJordan Brown {"850.cpg", 1, {0, 0}, {0, 0}, 0}, /* Multilingual Latin1 */
75bbf6f00cSJordan Brown {"950.cpg", 2, {1, 0}, {1, 0}, 0}, /* Chinese Traditional */
76bbf6f00cSJordan Brown {"1252.cpg", 1, {2, 0}, {2, 0}, 0}, /* MS Latin1 */
77bbf6f00cSJordan Brown {"949.cpg", 2, {3, 0}, {3, 0}, 0}, /* Korean */
78bbf6f00cSJordan Brown {"936.cpg", 2, {4, 0}, {4, 0}, 0}, /* Chinese Simplified */
79bbf6f00cSJordan Brown {"932.cpg", 2, {5, 0}, {5, 0}, 0}, /* Japanese */
80bbf6f00cSJordan Brown {"852.cpg", 1, {6, 0}, {6, 0}, 0}, /* Multilingual Latin2 */
81bbf6f00cSJordan Brown {"1250.cpg", 1, {7, 0}, {7, 0}, 0}, /* MS Latin2 */
82bbf6f00cSJordan Brown {"1253.cpg", 1, {8, 0}, {8, 0}, 0}, /* MS Greek */
83bbf6f00cSJordan Brown {"737.cpg", 1, {9, 0}, {9, 0}, 0}, /* Greek */
84bbf6f00cSJordan Brown {"1254.cpg", 1, {10, 0}, {10, 0}, 0}, /* MS Turkish */
85bbf6f00cSJordan Brown {"857.cpg", 1, {11, 0}, {11, 0}, 0}, /* Multilingual Latin5 */
86bbf6f00cSJordan Brown {"1251.cpg", 1, {12, 0}, {12, 0}, 0}, /* MS Cyrillic */
87bbf6f00cSJordan Brown {"866.cpg", 1, {13, 0}, {13, 0}, 0}, /* Cyrillic II */
88bbf6f00cSJordan Brown {"1255.cpg", 1, {14, 0}, {14, 0}, 0}, /* MS Hebrew */
89bbf6f00cSJordan Brown {"862.cpg", 1, {15, 0}, {15, 0}, 0}, /* Hebrew */
90bbf6f00cSJordan Brown {"1256.cpg", 1, {16, 0}, {16, 0}, 0}, /* MS Arabic */
91bbf6f00cSJordan Brown {"720.cpg", 1, {17, 0}, {17, 0}, 0} /* Arabic */
92da6c28aaSamw };
93da6c28aaSamw
94bbf6f00cSJordan Brown #define MAX_OEMPAGES (sizeof (oemcpg_table) / sizeof (oemcpg_table[0]))
95bbf6f00cSJordan Brown #define MAX_UNICODE_IDX 65536
96da6c28aaSamw
97da6c28aaSamw /*
98bbf6f00cSJordan Brown * The default SMB OEM codepage for English is codepage 850.
99da6c28aaSamw */
1008622ec45SGordon Ross const smb_wchar_t oem_codepage_850[256] = {
101da6c28aaSamw 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
102da6c28aaSamw 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
103da6c28aaSamw 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
104da6c28aaSamw 0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F,
105da6c28aaSamw 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
106da6c28aaSamw 0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F,
107da6c28aaSamw 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
108da6c28aaSamw 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F,
109da6c28aaSamw 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
110da6c28aaSamw 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F,
111da6c28aaSamw 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
112da6c28aaSamw 0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F,
113da6c28aaSamw 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
114da6c28aaSamw 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
115da6c28aaSamw 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
116da6c28aaSamw 0x0078, 0x0079, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F,
117da6c28aaSamw 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
118da6c28aaSamw 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
119da6c28aaSamw 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
120da6c28aaSamw 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
121da6c28aaSamw 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA,
122da6c28aaSamw 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
123da6c28aaSamw 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0,
124da6c28aaSamw 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
125da6c28aaSamw 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3,
126da6c28aaSamw 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
127da6c28aaSamw 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE,
128da6c28aaSamw 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
129da6c28aaSamw 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE,
130da6c28aaSamw 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
131da6c28aaSamw 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8,
132da6c28aaSamw 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
133da6c28aaSamw };
134da6c28aaSamw
135da6c28aaSamw /*
136bbf6f00cSJordan Brown * The default telnet OEM codepage for English is codepage 1252.
137da6c28aaSamw */
1388622ec45SGordon Ross const smb_wchar_t oem_codepage_1252[256] = {
139da6c28aaSamw 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8,
140da6c28aaSamw 0x9, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x10,
141da6c28aaSamw 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
142da6c28aaSamw 0x19, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x001F, 0x20,
143da6c28aaSamw 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
144da6c28aaSamw 0x29, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 0x30,
145da6c28aaSamw 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
146da6c28aaSamw 0x39, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E, 0x003F, 0x40,
147da6c28aaSamw 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
148da6c28aaSamw 0x49, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x50,
149da6c28aaSamw 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
150da6c28aaSamw 0x59, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x005F, 0x60,
151da6c28aaSamw 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
152da6c28aaSamw 0x69, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x70,
153da6c28aaSamw 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
154da6c28aaSamw 0x79, 0x007A, 0x007B, 0x007C, 0x007D, 0x007E, 0x007F, 0x20AC,
155da6c28aaSamw 0x81, 0x201A, 0x192, 0x201E, 0x2026, 0x2020, 0x2021, 0x02C6,
156da6c28aaSamw 0x2030, 0x160, 0x2039, 0x152, 0x8D, 0x017D, 0x8F, 0x90,
157da6c28aaSamw 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014, 0x02DC,
158da6c28aaSamw 0x2122, 0x161, 0x203A, 0x153, 0x9D, 0x017E, 0x178, 0x00A0,
159da6c28aaSamw 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8,
160da6c28aaSamw 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, 0x00B0,
161da6c28aaSamw 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8,
162da6c28aaSamw 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0,
163da6c28aaSamw 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8,
164da6c28aaSamw 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0,
165da6c28aaSamw 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8,
166da6c28aaSamw 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0,
167da6c28aaSamw 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8,
168da6c28aaSamw 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0,
169da6c28aaSamw 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8,
170da6c28aaSamw 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
171da6c28aaSamw };
172da6c28aaSamw
173bbf6f00cSJordan Brown static oempage_t *oem_get_oempage(uint32_t);
174bbf6f00cSJordan Brown static oempage_t *oem_get_ucspage(uint32_t);
175bbf6f00cSJordan Brown static void oem_codepage_init(uint32_t);
176bbf6f00cSJordan Brown static void oem_codepage_setup(uint32_t);
177da6c28aaSamw
178da6c28aaSamw /*
179bbf6f00cSJordan Brown * Convert a unicode string to an oem string.
180da6c28aaSamw *
181bbf6f00cSJordan Brown * The conversion will stop at the end of the unicode string
182bbf6f00cSJordan Brown * or when (nbytes - 1) oem characters have been stored.
183da6c28aaSamw *
184bbf6f00cSJordan Brown * The number of converted unicode characters is returned,
185bbf6f00cSJordan Brown * or 0 on error.
186da6c28aaSamw */
187da6c28aaSamw size_t
ucstooem(char * oem,const smb_wchar_t * ucs,size_t nbytes,uint32_t cpid)188bbf6f00cSJordan Brown ucstooem(char *oem, const smb_wchar_t *ucs, size_t nbytes, uint32_t cpid)
189da6c28aaSamw {
190bbf6f00cSJordan Brown oempage_t *ucspage;
191bbf6f00cSJordan Brown uint32_t count = 0;
192bbf6f00cSJordan Brown smb_wchar_t oemchar;
193da6c28aaSamw
194bbf6f00cSJordan Brown if (ucs == NULL || oem == NULL)
195da6c28aaSamw return (0);
196da6c28aaSamw
197bbf6f00cSJordan Brown if ((ucspage = oem_get_ucspage(cpid)) == NULL)
198da6c28aaSamw return (0);
199da6c28aaSamw
200bbf6f00cSJordan Brown while (nbytes != 0 && (oemchar = ucspage->value[*ucs]) != 0) {
201da6c28aaSamw if (oemchar & 0xff00 && nbytes >= MTS_MB_CHAR_MAX) {
202bbf6f00cSJordan Brown *oem++ = oemchar >> 8;
203bbf6f00cSJordan Brown *oem++ = (char)oemchar;
204da6c28aaSamw nbytes -= 2;
205da6c28aaSamw } else if (nbytes > 1) {
206bbf6f00cSJordan Brown *oem++ = (char)oemchar;
207da6c28aaSamw nbytes--;
208bbf6f00cSJordan Brown } else {
209da6c28aaSamw break;
210bbf6f00cSJordan Brown }
211da6c28aaSamw
212da6c28aaSamw count++;
213bbf6f00cSJordan Brown ucs++;
214da6c28aaSamw }
215da6c28aaSamw
216bbf6f00cSJordan Brown *oem = '\0';
217da6c28aaSamw return (count);
218da6c28aaSamw }
219da6c28aaSamw
220da6c28aaSamw /*
221bbf6f00cSJordan Brown * Convert an oem string to a unicode string.
222da6c28aaSamw *
223bbf6f00cSJordan Brown * The conversion will stop at the end of the oem string or
224bbf6f00cSJordan Brown * when nwchars - 1 have been converted.
225bbf6f00cSJordan Brown *
226bbf6f00cSJordan Brown * The number of converted oem chars is returned, or 0 on error.
227bbf6f00cSJordan Brown * An oem char may be either 1 or 2 bytes.
228da6c28aaSamw */
229da6c28aaSamw size_t
oemtoucs(smb_wchar_t * ucs,const char * oem,size_t nwchars,uint32_t cpid)230bbf6f00cSJordan Brown oemtoucs(smb_wchar_t *ucs, const char *oem, size_t nwchars, uint32_t cpid)
231da6c28aaSamw {
232bbf6f00cSJordan Brown oempage_t *oempage;
233bbf6f00cSJordan Brown size_t count = nwchars;
234bbf6f00cSJordan Brown smb_wchar_t oemchar;
235da6c28aaSamw
236bbf6f00cSJordan Brown if (ucs == NULL || oem == NULL)
237da6c28aaSamw return (0);
238da6c28aaSamw
239bbf6f00cSJordan Brown if ((oempage = oem_get_oempage(cpid)) == NULL)
240da6c28aaSamw return (0);
241da6c28aaSamw
242bbf6f00cSJordan Brown while ((oemchar = (smb_wchar_t)*oem++ & 0xff) != 0) {
243da6c28aaSamw /*
244bbf6f00cSJordan Brown * Cannot find one byte oemchar in table.
245bbf6f00cSJordan Brown * Must be a lead byte. Try two bytes.
246da6c28aaSamw */
247da6c28aaSamw if ((oempage->value[oemchar] == 0) && (oemchar != 0)) {
248bbf6f00cSJordan Brown oemchar = oemchar << 8 | (*oem++ & 0xff);
249da6c28aaSamw if (oempage->value[oemchar] == 0) {
250bbf6f00cSJordan Brown *ucs = 0;
251da6c28aaSamw break;
252da6c28aaSamw }
253da6c28aaSamw }
254da6c28aaSamw #ifdef _BIG_ENDIAN
255bbf6f00cSJordan Brown *ucs = LE_IN16(&oempage->value[oemchar]);
256da6c28aaSamw #else
257bbf6f00cSJordan Brown *ucs = oempage->value[oemchar];
258da6c28aaSamw #endif
259da6c28aaSamw count--;
260bbf6f00cSJordan Brown ucs++;
261da6c28aaSamw }
262da6c28aaSamw
263bbf6f00cSJordan Brown *ucs = 0;
264da6c28aaSamw return (nwchars - count);
265da6c28aaSamw }
266da6c28aaSamw
267da6c28aaSamw /*
268bbf6f00cSJordan Brown * Get a pointer to the oem page for the specific codepage id.
269da6c28aaSamw */
270bbf6f00cSJordan Brown static oempage_t *
oem_get_oempage(uint32_t cpid)271bbf6f00cSJordan Brown oem_get_oempage(uint32_t cpid)
272da6c28aaSamw {
273bbf6f00cSJordan Brown if (cpid >= MAX_OEMPAGES)
274bbf6f00cSJordan Brown return (NULL);
275bbf6f00cSJordan Brown
276bbf6f00cSJordan Brown if (!oemcpg_table[cpid].valid) {
277bbf6f00cSJordan Brown oem_codepage_init(cpid);
278bbf6f00cSJordan Brown
279bbf6f00cSJordan Brown if (!oemcpg_table[cpid].valid)
280bbf6f00cSJordan Brown return (NULL);
281bbf6f00cSJordan Brown }
282bbf6f00cSJordan Brown
283bbf6f00cSJordan Brown return (&oemcpg_table[cpid].oempage);
284da6c28aaSamw }
285da6c28aaSamw
286da6c28aaSamw /*
287bbf6f00cSJordan Brown * Get a pointer to the ucs page for the specific codepage id.
288da6c28aaSamw */
289bbf6f00cSJordan Brown static oempage_t *
oem_get_ucspage(uint32_t cpid)290bbf6f00cSJordan Brown oem_get_ucspage(uint32_t cpid)
291da6c28aaSamw {
292bbf6f00cSJordan Brown if (cpid >= MAX_OEMPAGES)
293bbf6f00cSJordan Brown return (NULL);
294da6c28aaSamw
295bbf6f00cSJordan Brown if (!oemcpg_table[cpid].valid) {
296bbf6f00cSJordan Brown oem_codepage_init(cpid);
297bbf6f00cSJordan Brown
298bbf6f00cSJordan Brown if (!oemcpg_table[cpid].valid)
299bbf6f00cSJordan Brown return (NULL);
300bbf6f00cSJordan Brown }
301bbf6f00cSJordan Brown
302bbf6f00cSJordan Brown return (&oemcpg_table[cpid].ucspage);
303bbf6f00cSJordan Brown }
304da6c28aaSamw
305da6c28aaSamw /*
306bbf6f00cSJordan Brown * Initialize the oem page in the oem table.
307da6c28aaSamw */
308bbf6f00cSJordan Brown static void
oem_codepage_init(uint32_t cpid)309bbf6f00cSJordan Brown oem_codepage_init(uint32_t cpid)
310da6c28aaSamw {
311*b819cea2SGordon Ross #if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
312bbf6f00cSJordan Brown static mutex_t mutex;
313da6c28aaSamw
314bbf6f00cSJordan Brown (void) mutex_lock(&mutex);
315bbf6f00cSJordan Brown oem_codepage_setup(cpid);
316bbf6f00cSJordan Brown (void) mutex_unlock(&mutex);
317bbf6f00cSJordan Brown #else
318bbf6f00cSJordan Brown static kmutex_t mutex;
319da6c28aaSamw
320bbf6f00cSJordan Brown mutex_enter(&mutex);
321bbf6f00cSJordan Brown oem_codepage_setup(cpid);
322bbf6f00cSJordan Brown mutex_exit(&mutex);
323bbf6f00cSJordan Brown #endif /* _KERNEL */
324bbf6f00cSJordan Brown }
325da6c28aaSamw
326bbf6f00cSJordan Brown static void
oem_codepage_setup(uint32_t cpid)327bbf6f00cSJordan Brown oem_codepage_setup(uint32_t cpid)
328bbf6f00cSJordan Brown {
3298622ec45SGordon Ross const smb_wchar_t *default_oem_cp;
330bbf6f00cSJordan Brown oem_codepage_t *oemcpg;
331bbf6f00cSJordan Brown uint32_t bytesperchar;
332bbf6f00cSJordan Brown uint32_t max_oem_index;
333bbf6f00cSJordan Brown int i;
334bbf6f00cSJordan Brown
335bbf6f00cSJordan Brown switch (cpid) {
336bbf6f00cSJordan Brown case OEM_CPG_850:
337bbf6f00cSJordan Brown default_oem_cp = oem_codepage_850;
338bbf6f00cSJordan Brown break;
339bbf6f00cSJordan Brown case OEM_CPG_1252:
340bbf6f00cSJordan Brown default_oem_cp = oem_codepage_1252;
341bbf6f00cSJordan Brown default:
342da6c28aaSamw return;
343da6c28aaSamw }
344da6c28aaSamw
345bbf6f00cSJordan Brown oemcpg = &oemcpg_table[cpid];
346bbf6f00cSJordan Brown if (oemcpg->valid)
347da6c28aaSamw return;
348da6c28aaSamw
349da6c28aaSamw /*
350bbf6f00cSJordan Brown * max_oem_index will be 256 or 65536 dependent
351bbf6f00cSJordan Brown * on the OEM codepage.
352da6c28aaSamw */
353bbf6f00cSJordan Brown bytesperchar = oemcpg_table[cpid].bytesperchar;
354bbf6f00cSJordan Brown max_oem_index = 1 << (bytesperchar * 8);
355da6c28aaSamw
356bbf6f00cSJordan Brown oemcpg->oempage.value =
357bbf6f00cSJordan Brown MEM_ZALLOC("oem", max_oem_index * sizeof (smb_wchar_t));
358bbf6f00cSJordan Brown if (oemcpg->oempage.value == NULL)
359bbf6f00cSJordan Brown return;
360da6c28aaSamw
361bbf6f00cSJordan Brown oemcpg->ucspage.value =
362bbf6f00cSJordan Brown MEM_ZALLOC("oem", MAX_UNICODE_IDX * sizeof (smb_wchar_t));
363bbf6f00cSJordan Brown if (oemcpg->ucspage.value == NULL) {
364bbf6f00cSJordan Brown MEM_FREE("oem", oemcpg->oempage.value);
365bbf6f00cSJordan Brown oemcpg->oempage.value = NULL;
366bbf6f00cSJordan Brown return;
367bbf6f00cSJordan Brown }
368da6c28aaSamw
369bbf6f00cSJordan Brown for (i = 0; i < max_oem_index; i++) {
370bbf6f00cSJordan Brown oemcpg->oempage.value[i] = default_oem_cp[i];
371bbf6f00cSJordan Brown oemcpg->ucspage.value[default_oem_cp[i]] = (smb_wchar_t)i;
372bbf6f00cSJordan Brown }
373da6c28aaSamw
374bbf6f00cSJordan Brown oemcpg->valid = B_TRUE;
375da6c28aaSamw }
376