0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/module.h>
0011 #include <linux/kernel.h>
0012 #include <linux/string.h>
0013 #include <linux/nls.h>
0014 #include <linux/errno.h>
0015
0016 static const wchar_t charset2uni[256] = {
0017
0018 0x0000, 0x0001, 0x0002, 0x0003,
0019 0x0004, 0x0005, 0x0006, 0x0007,
0020 0x0008, 0x0009, 0x000a, 0x000b,
0021 0x000c, 0x000d, 0x000e, 0x000f,
0022
0023 0x0010, 0x0011, 0x0012, 0x0013,
0024 0x0014, 0x0015, 0x0016, 0x0017,
0025 0x0018, 0x0019, 0x001a, 0x001b,
0026 0x001c, 0x001d, 0x001e, 0x001f,
0027
0028 0x0020, 0x0021, 0x0022, 0x0023,
0029 0x0024, 0x0025, 0x0026, 0x0027,
0030 0x0028, 0x0029, 0x002a, 0x002b,
0031 0x002c, 0x002d, 0x002e, 0x002f,
0032
0033 0x0030, 0x0031, 0x0032, 0x0033,
0034 0x0034, 0x0035, 0x0036, 0x0037,
0035 0x0038, 0x0039, 0x003a, 0x003b,
0036 0x003c, 0x003d, 0x003e, 0x003f,
0037
0038 0x0040, 0x0041, 0x0042, 0x0043,
0039 0x0044, 0x0045, 0x0046, 0x0047,
0040 0x0048, 0x0049, 0x004a, 0x004b,
0041 0x004c, 0x004d, 0x004e, 0x004f,
0042
0043 0x0050, 0x0051, 0x0052, 0x0053,
0044 0x0054, 0x0055, 0x0056, 0x0057,
0045 0x0058, 0x0059, 0x005a, 0x005b,
0046 0x005c, 0x005d, 0x005e, 0x005f,
0047
0048 0x0060, 0x0061, 0x0062, 0x0063,
0049 0x0064, 0x0065, 0x0066, 0x0067,
0050 0x0068, 0x0069, 0x006a, 0x006b,
0051 0x006c, 0x006d, 0x006e, 0x006f,
0052
0053 0x0070, 0x0071, 0x0072, 0x0073,
0054 0x0074, 0x0075, 0x0076, 0x0077,
0055 0x0078, 0x0079, 0x007a, 0x007b,
0056 0x007c, 0x007d, 0x007e, 0x007f,
0057
0058 0x0402, 0x0403, 0x201a, 0x0453,
0059 0x201e, 0x2026, 0x2020, 0x2021,
0060 0x20ac, 0x2030, 0x0409, 0x2039,
0061 0x040a, 0x040c, 0x040b, 0x040f,
0062
0063 0x0452, 0x2018, 0x2019, 0x201c,
0064 0x201d, 0x2022, 0x2013, 0x2014,
0065 0x0000, 0x2122, 0x0459, 0x203a,
0066 0x045a, 0x045c, 0x045b, 0x045f,
0067
0068 0x00a0, 0x040e, 0x045e, 0x0408,
0069 0x00a4, 0x0490, 0x00a6, 0x00a7,
0070 0x0401, 0x00a9, 0x0404, 0x00ab,
0071 0x00ac, 0x00ad, 0x00ae, 0x0407,
0072
0073 0x00b0, 0x00b1, 0x0406, 0x0456,
0074 0x0491, 0x00b5, 0x00b6, 0x00b7,
0075 0x0451, 0x2116, 0x0454, 0x00bb,
0076 0x0458, 0x0405, 0x0455, 0x0457,
0077
0078 0x0410, 0x0411, 0x0412, 0x0413,
0079 0x0414, 0x0415, 0x0416, 0x0417,
0080 0x0418, 0x0419, 0x041a, 0x041b,
0081 0x041c, 0x041d, 0x041e, 0x041f,
0082
0083 0x0420, 0x0421, 0x0422, 0x0423,
0084 0x0424, 0x0425, 0x0426, 0x0427,
0085 0x0428, 0x0429, 0x042a, 0x042b,
0086 0x042c, 0x042d, 0x042e, 0x042f,
0087
0088 0x0430, 0x0431, 0x0432, 0x0433,
0089 0x0434, 0x0435, 0x0436, 0x0437,
0090 0x0438, 0x0439, 0x043a, 0x043b,
0091 0x043c, 0x043d, 0x043e, 0x043f,
0092
0093 0x0440, 0x0441, 0x0442, 0x0443,
0094 0x0444, 0x0445, 0x0446, 0x0447,
0095 0x0448, 0x0449, 0x044a, 0x044b,
0096 0x044c, 0x044d, 0x044e, 0x044f,
0097 };
0098
0099 static const unsigned char page00[256] = {
0100 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0101 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0102 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0103 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0104 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0105 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0106 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0107 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0108 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0109 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0110 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0111 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0112 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0113 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0114 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0115 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0116
0117 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0118 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0120 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0121 0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7,
0122 0x00, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00,
0123 0xb0, 0xb1, 0x00, 0x00, 0x00, 0xb5, 0xb6, 0xb7,
0124 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0125 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0126 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0127 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0128 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0129 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0130 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0131 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0132 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00,
0133 };
0134
0135 static const unsigned char page04[256] = {
0136 0x00, 0xa8, 0x80, 0x81, 0xaa, 0xbd, 0xb2, 0xaf,
0137 0xa3, 0x8a, 0x8c, 0x8e, 0x8d, 0x00, 0xa1, 0x8f,
0138 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0139 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0140 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0141 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0142 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0143 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0144 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0145 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0146 0x00, 0xb8, 0x90, 0x83, 0xba, 0xbe, 0xb3, 0xbf,
0147 0xbc, 0x9a, 0x9c, 0x9e, 0x9d, 0x00, 0xa2, 0x9f,
0148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0152
0153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0155 0x00, 0xa5, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00,
0156 };
0157
0158 static const unsigned char page20[256] = {
0159 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0160 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0161 0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00,
0162 0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00,
0163 0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00,
0164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0165 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0166 0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00,
0167 };
0168
0169 static const unsigned char page21[256] = {
0170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0172 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x00,
0173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0174 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00,
0175 };
0176
0177 static const unsigned char *const page_uni2charset[256] = {
0178 page00, NULL, NULL, NULL, page04, NULL, NULL, NULL,
0179 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0180 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0181 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
0182 page20, page21, NULL, NULL, NULL, NULL, NULL, NULL,
0183 };
0184
0185 static const unsigned char charset2lower[256] = {
0186 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0187 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0188 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0189 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0190 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0191 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0192 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0193 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0194 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0195 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0196 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0197 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0198 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0199 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0200 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0201 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0202 0x90, 0x83, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0203 0x88, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f,
0204 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0205 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0206 0xa0, 0xa2, 0xa2, 0xbc, 0xa4, 0xb4, 0xa6, 0xa7,
0207 0xb8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf,
0208 0xb0, 0xb1, 0xb3, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0209 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbe, 0xbe, 0xbf,
0210 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0211 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0212 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0213 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0214 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0215 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0216 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0217 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
0218 };
0219
0220 static const unsigned char charset2upper[256] = {
0221 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0222 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0223 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0224 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0225 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0226 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0227 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0228 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0229 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0230 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0231 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0232 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0233 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0234 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0235 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0236 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0237 0x80, 0x81, 0x82, 0x81, 0x84, 0x85, 0x86, 0x87,
0238 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0239 0x80, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0240 0x98, 0x99, 0x8a, 0x9b, 0x8c, 0x8d, 0x8e, 0x8f,
0241 0xa0, 0xa1, 0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0242 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0243 0xb0, 0xb1, 0xb2, 0xb2, 0xa5, 0xb5, 0xb6, 0xb7,
0244 0xa8, 0xb9, 0xaa, 0xbb, 0xa3, 0xbd, 0xbd, 0xaf,
0245 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0246 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0247 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0248 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0249 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0250 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0251 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0252 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0253 };
0254
0255 static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
0256 {
0257 const unsigned char *uni2charset;
0258 unsigned char cl = uni & 0x00ff;
0259 unsigned char ch = (uni & 0xff00) >> 8;
0260
0261 if (boundlen <= 0)
0262 return -ENAMETOOLONG;
0263
0264 uni2charset = page_uni2charset[ch];
0265 if (uni2charset && uni2charset[cl])
0266 out[0] = uni2charset[cl];
0267 else
0268 return -EINVAL;
0269 return 1;
0270 }
0271
0272 static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
0273 {
0274 *uni = charset2uni[*rawstring];
0275 if (*uni == 0x0000)
0276 return -EINVAL;
0277 return 1;
0278 }
0279
0280 static struct nls_table table = {
0281 .charset = "cp1251",
0282 .uni2char = uni2char,
0283 .char2uni = char2uni,
0284 .charset2lower = charset2lower,
0285 .charset2upper = charset2upper,
0286 };
0287
0288 static int __init init_nls_cp1251(void)
0289 {
0290 return register_nls(&table);
0291 }
0292
0293 static void __exit exit_nls_cp1251(void)
0294 {
0295 unregister_nls(&table);
0296 }
0297
0298 module_init(init_nls_cp1251)
0299 module_exit(exit_nls_cp1251)
0300
0301 MODULE_LICENSE("Dual BSD/GPL");