Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/os/kiconv.c
+++ new/usr/src/uts/common/os/kiconv.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 26 /*
29 27 * Kernel iconv code conversion functions (PSARC/2007/173).
30 28 *
31 29 * Man pages: kiconv_open(9F), kiconv(9F), kiconv_close(9F), and kiconvstr(9F).
32 30 * Interface stability: Committed.
33 31 */
34 32
35 33 #include <sys/types.h>
36 34 #include <sys/param.h>
37 35 #include <sys/sysmacros.h>
38 36 #include <sys/systm.h>
39 37 #include <sys/debug.h>
40 38 #include <sys/kmem.h>
41 39 #include <sys/sunddi.h>
42 40 #include <sys/ksynch.h>
43 41 #include <sys/modctl.h>
44 42 #include <sys/byteorder.h>
45 43 #include <sys/errno.h>
46 44 #include <sys/kiconv.h>
47 45 #include <sys/kiconv_latin1.h>
48 46
49 47
50 48 /*
51 49 * The following macros indicate ids to the correct code conversion mapping
52 50 * data tables to use. The actual tables are coming from <sys/kiconv_latin1.h>.
53 51 */
54 52 #define KICONV_TBLID_1252 (0x00)
55 53 #define KICONV_TBLID_8859_1 (0x01)
56 54 #define KICONV_TBLID_8859_15 (0x02)
57 55 #define KICONV_TBLID_850 (0x03)
58 56
59 57 #define KICONV_MAX_MAPPING_TBLID (0x03)
60 58
61 59 /*
62 60 * The following tables are coming from u8_textprep.c. We use them to
63 61 * check on validity of UTF-8 characters and their bytes.
64 62 */
65 63 extern const int8_t u8_number_of_bytes[];
66 64 extern const uint8_t u8_valid_min_2nd_byte[];
67 65 extern const uint8_t u8_valid_max_2nd_byte[];
68 66
69 67
70 68 /*
71 69 * The following four functions, open_to_1252(), open_to_88591(),
72 70 * open_to_885915(), and open_to_850(), are kiconv_open functions from
73 71 * UTF-8 to corresponding single byte codesets.
74 72 */
75 73 static void *
76 74 open_to_1252()
77 75 {
78 76 kiconv_state_t s;
79 77
80 78 s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
81 79 s->id = KICONV_TBLID_1252;
82 80 s->bom_processed = 0;
83 81
84 82 return ((void *)s);
85 83 }
86 84
87 85 static void *
88 86 open_to_88591()
89 87 {
90 88 kiconv_state_t s;
91 89
92 90 s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
93 91 s->id = KICONV_TBLID_8859_1;
94 92 s->bom_processed = 0;
95 93
96 94 return ((void *)s);
97 95 }
98 96
99 97 static void *
100 98 open_to_885915()
101 99 {
102 100 kiconv_state_t s;
103 101
104 102 s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
105 103 s->id = KICONV_TBLID_8859_15;
106 104 s->bom_processed = 0;
107 105
108 106 return ((void *)s);
109 107 }
110 108
111 109 static void *
112 110 open_to_850()
113 111 {
114 112 kiconv_state_t s;
115 113
116 114 s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
117 115 s->id = KICONV_TBLID_850;
118 116 s->bom_processed = 0;
119 117
120 118 return ((void *)s);
121 119 }
122 120
123 121 /*
124 122 * The following four functions, open_fr_1252(), open_fr_88591(),
125 123 * open_fr_885915(), and open_fr_850(), are kiconv_open functions from
126 124 * corresponding single byte codesets to UTF-8.
127 125 */
128 126 static void *
129 127 open_fr_1252()
130 128 {
131 129 return ((void *)KICONV_TBLID_1252);
132 130 }
133 131
134 132 static void *
135 133 open_fr_88591()
136 134 {
137 135 return ((void *)KICONV_TBLID_8859_1);
138 136 }
139 137
140 138 static void *
141 139 open_fr_885915()
142 140 {
143 141 return ((void *)KICONV_TBLID_8859_15);
144 142 }
145 143
146 144 static void *
147 145 open_fr_850()
148 146 {
149 147 return ((void *)KICONV_TBLID_850);
150 148 }
151 149
152 150 /*
153 151 * The following close_to_sb() function is kiconv_close function for
154 152 * the conversions from UTF-8 to single byte codesets. The close_fr_sb()
155 153 * is kiconv_close function for the conversions from single byte codesets to
156 154 * UTF-8.
157 155 */
158 156 static int
159 157 close_to_sb(void *s)
160 158 {
161 159 if (! s || s == (void *)-1)
162 160 return (EBADF);
163 161
164 162 kmem_free(s, sizeof (kiconv_state_data_t));
165 163
166 164 return (0);
167 165 }
168 166
169 167 static int
170 168 close_fr_sb(void *s)
171 169 {
172 170 if ((ulong_t)s > KICONV_MAX_MAPPING_TBLID)
173 171 return (EBADF);
174 172
175 173 return (0);
176 174 }
177 175
178 176 /*
179 177 * The following is the common kiconv function for conversions from UTF-8
180 178 * to single byte codesets.
181 179 */
182 180 static size_t
183 181 kiconv_to_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
184 182 size_t *outbytesleft, int *errno)
185 183 {
186 184 size_t id;
187 185 size_t ret_val;
188 186 uchar_t *ib;
189 187 uchar_t *oldib;
190 188 uchar_t *ob;
191 189 uchar_t *ibtail;
192 190 uchar_t *obtail;
193 191 uint32_t u8;
194 192 size_t i;
195 193 size_t l;
196 194 size_t h;
197 195 size_t init_h;
198 196 int8_t sz;
199 197 boolean_t second;
200 198
201 199 /* Check on the kiconv code conversion descriptor. */
202 200 if (! kcd || kcd == (void *)-1) {
203 201 *errno = EBADF;
204 202 return ((size_t)-1);
205 203 }
206 204
207 205 /*
208 206 * Get the table id we are going to use for the code conversion
209 207 * and let's double check on it.
210 208 */
211 209 id = ((kiconv_state_t)kcd)->id;
212 210 if (id > KICONV_MAX_MAPPING_TBLID) {
213 211 *errno = EBADF;
214 212 return ((size_t)-1);
215 213 }
216 214
217 215 /* If this is a state reset request, process and return. */
218 216 if (! inbuf || ! (*inbuf)) {
219 217 ((kiconv_state_t)kcd)->bom_processed = 0;
220 218 return ((size_t)0);
221 219 }
222 220
223 221 ret_val = 0;
224 222 ib = (uchar_t *)*inbuf;
225 223 ob = (uchar_t *)*outbuf;
226 224 ibtail = ib + *inbytesleft;
227 225 obtail = ob + *outbytesleft;
228 226
229 227 /*
230 228 * The inital high value for the binary search we will be using
231 229 * shortly is a literal constant as of today but to be future proof,
232 230 * let's calculate it like the following at here.
233 231 */
234 232 init_h = sizeof (to_sb_tbl[id]) / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
235 233
236 234 /*
237 235 * If we haven't checked on the UTF-8 signature BOM character in
238 236 * the beginning of the conversion data stream, we check it and if
239 237 * find one, we skip it since we have no use for it.
240 238 */
241 239 if (((kiconv_state_t)kcd)->bom_processed == 0 && (ibtail - ib) >= 3 &&
242 240 *ib == 0xef && *(ib + 1) == 0xbb && *(ib + 2) == 0xbf)
243 241 ib += 3;
244 242 ((kiconv_state_t)kcd)->bom_processed = 1;
245 243
246 244 while (ib < ibtail) {
247 245 sz = u8_number_of_bytes[*ib];
248 246 if (sz <= 0) {
249 247 *errno = EILSEQ;
250 248 ret_val = (size_t)-1;
251 249 break;
252 250 }
253 251
254 252 /*
255 253 * If there is no room to write at the output buffer,
256 254 * issue E2BIG error.
257 255 */
258 256 if (ob >= obtail) {
259 257 *errno = E2BIG;
260 258 ret_val = (size_t)-1;
261 259 break;
262 260 }
263 261
264 262 /*
265 263 * If it is a 7-bit ASCII character, we don't need to
266 264 * process further and we just copy the character over.
267 265 *
268 266 * If not, we collect the character bytes up to four bytes,
269 267 * validate the bytes, and binary search for the corresponding
270 268 * single byte codeset character byte. If we find it from
271 269 * the mapping table, we put that into the output buffer;
272 270 * otherwise, we put a replacement character instead as
273 271 * a non-identical conversion.
274 272 */
275 273 if (sz == 1) {
276 274 *ob++ = *ib++;
277 275 continue;
278 276 }
279 277
280 278 /*
281 279 * Issue EINVAL error if input buffer has an incomplete
282 280 * character at the end of the buffer.
283 281 */
284 282 if ((ibtail - ib) < sz) {
285 283 *errno = EINVAL;
286 284 ret_val = (size_t)-1;
287 285 break;
288 286 }
289 287
290 288 /*
291 289 * We collect UTF-8 character bytes and also check if
292 290 * this is a valid UTF-8 character without any bogus bytes
293 291 * based on the latest UTF-8 binary representation.
294 292 */
295 293 oldib = ib;
296 294 u8 = *ib++;
297 295 second = B_TRUE;
298 296 for (i = 1; i < sz; i++) {
299 297 if (second) {
300 298 if (*ib < u8_valid_min_2nd_byte[u8] ||
301 299 *ib > u8_valid_max_2nd_byte[u8]) {
302 300 *errno = EILSEQ;
303 301 ret_val = (size_t)-1;
304 302 ib = oldib;
305 303 goto TO_SB_ILLEGAL_CHAR_ERR;
306 304 }
307 305 second = B_FALSE;
308 306 } else if (*ib < 0x80 || *ib > 0xbf) {
309 307 *errno = EILSEQ;
310 308 ret_val = (size_t)-1;
311 309 ib = oldib;
312 310 goto TO_SB_ILLEGAL_CHAR_ERR;
313 311 }
314 312 u8 = (u8 << 8) | ((uint32_t)*ib);
315 313 ib++;
316 314 }
317 315
318 316 i = l = 0;
319 317 h = init_h;
320 318 while (l <= h) {
321 319 i = (l + h) / 2;
322 320 if (to_sb_tbl[id][i].u8 == u8)
323 321 break;
324 322 else if (to_sb_tbl[id][i].u8 < u8)
325 323 l = i + 1;
326 324 else
327 325 h = i - 1;
328 326 }
329 327
330 328 if (to_sb_tbl[id][i].u8 == u8) {
331 329 *ob++ = to_sb_tbl[id][i].sb;
332 330 } else {
333 331 /*
334 332 * If we don't find a character in the target
335 333 * codeset, we insert an ASCII replacement character
336 334 * at the output buffer and indicate such
337 335 * "non-identical" conversion by increasing the
338 336 * return value which is the non-identical conversion
339 337 * counter if bigger than 0.
340 338 */
341 339 *ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
342 340 ret_val++;
343 341 }
344 342 }
345 343
346 344 TO_SB_ILLEGAL_CHAR_ERR:
347 345 *inbuf = (char *)ib;
348 346 *inbytesleft = ibtail - ib;
349 347 *outbuf = (char *)ob;
350 348 *outbytesleft = obtail - ob;
351 349
352 350 return (ret_val);
353 351 }
354 352
355 353 /*
356 354 * The following is the common kiconv function from single byte codesets to
357 355 * UTF-8.
358 356 */
359 357 static size_t
360 358 kiconv_fr_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
361 359 size_t *outbytesleft, int *errno)
362 360 {
363 361 size_t ret_val;
364 362 uchar_t *ib;
365 363 uchar_t *ob;
366 364 uchar_t *ibtail;
367 365 uchar_t *obtail;
368 366 size_t i;
369 367 size_t k;
370 368 int8_t sz;
371 369
372 370 /* Check on the kiconv code conversion descriptor validity. */
373 371 if ((ulong_t)kcd > KICONV_MAX_MAPPING_TBLID) {
374 372 *errno = EBADF;
375 373 return ((size_t)-1);
376 374 }
377 375
378 376 /*
379 377 * If this is a state reset request, there is nothing to do and so
380 378 * we just return.
381 379 */
382 380 if (! inbuf || ! (*inbuf))
383 381 return ((size_t)0);
384 382
385 383 ret_val = 0;
386 384 ib = (uchar_t *)*inbuf;
387 385 ob = (uchar_t *)*outbuf;
388 386 ibtail = ib + *inbytesleft;
389 387 obtail = ob + *outbytesleft;
390 388
391 389 while (ib < ibtail) {
392 390 /*
393 391 * If this is a 7-bit ASCII character, we just copy over and
394 392 * that's all we need to do for this character.
395 393 */
396 394 if (*ib < 0x80) {
397 395 if (ob >= obtail) {
398 396 *errno = E2BIG;
399 397 ret_val = (size_t)-1;
400 398 break;
401 399 }
402 400
403 401 *ob++ = *ib++;
404 402 continue;
405 403 }
406 404
407 405 /*
408 406 * Otherwise, we get the corresponding UTF-8 character bytes
409 407 * from the mapping table and copy them over.
410 408 *
411 409 * We don't need to worry about if the UTF-8 character bytes
412 410 * at the mapping tables are valid or not since they are good.
413 411 */
414 412 k = *ib - 0x80;
415 413 sz = u8_number_of_bytes[to_u8_tbl[(ulong_t)kcd][k].u8[0]];
416 414
417 415 /*
418 416 * If sz <= 0, that means we don't have any assigned character
419 417 * at the code point, k + 0x80, of the single byte codeset
420 418 * which is the fromcode. In other words, the input buffer
421 419 * has an illegal character.
422 420 */
423 421 if (sz <= 0) {
424 422 *errno = EILSEQ;
425 423 ret_val = (size_t)-1;
426 424 break;
427 425 }
428 426
429 427 if ((obtail - ob) < sz) {
430 428 *errno = E2BIG;
431 429 ret_val = (size_t)-1;
432 430 break;
433 431 }
434 432
435 433 for (i = 0; i < sz; i++)
436 434 *ob++ = to_u8_tbl[(ulong_t)kcd][k].u8[i];
437 435
438 436 ib++;
439 437 }
440 438
441 439 *inbuf = (char *)ib;
442 440 *inbytesleft = ibtail - ib;
443 441 *outbuf = (char *)ob;
444 442 *outbytesleft = obtail - ob;
445 443
446 444 return (ret_val);
447 445 }
448 446
449 447 /*
450 448 * The following is the common kiconvstr function from UTF-8 to single byte
451 449 * codesets.
452 450 */
453 451 static size_t
454 452 kiconvstr_to_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
455 453 size_t *outlen, int flag, int *errno)
456 454 {
457 455 size_t ret_val;
458 456 uchar_t *oldib;
459 457 uchar_t *ibtail;
460 458 uchar_t *obtail;
461 459 uint32_t u8;
462 460 size_t i;
463 461 size_t l;
464 462 size_t h;
465 463 size_t init_h;
466 464 int8_t sz;
467 465 boolean_t second;
468 466 boolean_t do_not_ignore_null;
469 467
470 468 /* Let's make sure that the table id is within the valid boundary. */
471 469 if (id > KICONV_MAX_MAPPING_TBLID) {
472 470 *errno = EBADF;
473 471 return ((size_t)-1);
474 472 }
475 473
476 474 ret_val = 0;
477 475 ibtail = ib + *inlen;
478 476 obtail = ob + *outlen;
479 477 do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
480 478 init_h = sizeof (to_sb_tbl[id]) / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
481 479
482 480 /* Skip any UTF-8 signature BOM character in the beginning. */
483 481 if ((ibtail - ib) >= 3 && *ib == 0xef && *(ib + 1) == 0xbb &&
484 482 *(ib + 2) == 0xbf)
485 483 ib += 3;
486 484
487 485 /*
488 486 * Basically this is pretty much the same as kiconv_to_sb() except
489 487 * that we are now accepting two flag values and doing the processing
490 488 * accordingly.
491 489 */
492 490 while (ib < ibtail) {
493 491 sz = u8_number_of_bytes[*ib];
494 492 if (sz <= 0) {
495 493 if (flag & KICONV_REPLACE_INVALID) {
496 494 if (ob >= obtail) {
497 495 *errno = E2BIG;
498 496 ret_val = (size_t)-1;
499 497 break;
500 498 }
501 499
502 500 ib++;
503 501 goto STR_TO_SB_REPLACE_INVALID;
504 502 }
505 503
506 504 *errno = EILSEQ;
507 505 ret_val = (size_t)-1;
508 506 break;
509 507 }
510 508
511 509 if (*ib == '\0' && do_not_ignore_null)
512 510 break;
513 511
514 512 if (ob >= obtail) {
515 513 *errno = E2BIG;
516 514 ret_val = (size_t)-1;
517 515 break;
518 516 }
519 517
520 518 if (sz == 1) {
521 519 *ob++ = *ib++;
522 520 continue;
523 521 }
524 522
525 523 if ((ibtail - ib) < sz) {
526 524 if (flag & KICONV_REPLACE_INVALID) {
527 525 ib = ibtail;
528 526 goto STR_TO_SB_REPLACE_INVALID;
529 527 }
530 528
531 529 *errno = EINVAL;
532 530 ret_val = (size_t)-1;
533 531 break;
534 532 }
535 533
536 534 oldib = ib;
537 535 u8 = *ib++;
538 536 second = B_TRUE;
539 537 for (i = 1; i < sz; i++) {
540 538 if (second) {
541 539 if (*ib < u8_valid_min_2nd_byte[u8] ||
542 540 *ib > u8_valid_max_2nd_byte[u8]) {
543 541 if (flag & KICONV_REPLACE_INVALID) {
544 542 ib = oldib + sz;
545 543 goto STR_TO_SB_REPLACE_INVALID;
546 544 }
547 545
548 546 *errno = EILSEQ;
549 547 ret_val = (size_t)-1;
550 548 ib = oldib;
551 549 goto STR_TO_SB_ILLEGAL_CHAR_ERR;
552 550 }
553 551 second = B_FALSE;
554 552 } else if (*ib < 0x80 || *ib > 0xbf) {
555 553 if (flag & KICONV_REPLACE_INVALID) {
556 554 ib = oldib + sz;
557 555 goto STR_TO_SB_REPLACE_INVALID;
558 556 }
559 557
560 558 *errno = EILSEQ;
561 559 ret_val = (size_t)-1;
562 560 ib = oldib;
563 561 goto STR_TO_SB_ILLEGAL_CHAR_ERR;
564 562 }
565 563 u8 = (u8 << 8) | ((uint32_t)*ib);
566 564 ib++;
567 565 }
568 566
569 567 i = l = 0;
570 568 h = init_h;
571 569 while (l <= h) {
572 570 i = (l + h) / 2;
573 571 if (to_sb_tbl[id][i].u8 == u8)
574 572 break;
575 573 else if (to_sb_tbl[id][i].u8 < u8)
576 574 l = i + 1;
577 575 else
578 576 h = i - 1;
579 577 }
580 578
581 579 if (to_sb_tbl[id][i].u8 == u8) {
582 580 *ob++ = to_sb_tbl[id][i].sb;
583 581 } else {
584 582 STR_TO_SB_REPLACE_INVALID:
585 583 *ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
586 584 ret_val++;
587 585 }
588 586 }
589 587
590 588 STR_TO_SB_ILLEGAL_CHAR_ERR:
591 589 *inlen = ibtail - ib;
592 590 *outlen = obtail - ob;
593 591
594 592 return (ret_val);
595 593 }
596 594
597 595 /*
598 596 * The following four functions are entry points recorded at the conv_list[]
599 597 * defined at below.
600 598 */
601 599 static size_t
602 600 kiconvstr_to_1252(char *inarray, size_t *inlen, char *outarray,
603 601 size_t *outlen, int flag, int *errno)
604 602 {
605 603 return (kiconvstr_to_sb(KICONV_TBLID_1252, (uchar_t *)inarray,
606 604 inlen, (uchar_t *)outarray, outlen, flag, errno));
607 605 }
608 606
609 607 static size_t
610 608 kiconvstr_to_1(char *inarray, size_t *inlen, char *outarray,
611 609 size_t *outlen, int flag, int *errno)
612 610 {
613 611 return (kiconvstr_to_sb(KICONV_TBLID_8859_1, (uchar_t *)inarray,
614 612 inlen, (uchar_t *)outarray, outlen, flag, errno));
615 613 }
616 614
617 615 static size_t
618 616 kiconvstr_to_15(char *inarray, size_t *inlen, char *outarray,
619 617 size_t *outlen, int flag, int *errno)
620 618 {
621 619 return (kiconvstr_to_sb(KICONV_TBLID_8859_15, (uchar_t *)inarray,
622 620 inlen, (uchar_t *)outarray, outlen, flag, errno));
623 621 }
624 622
625 623 static size_t
626 624 kiconvstr_to_850(char *inarray, size_t *inlen, char *outarray,
627 625 size_t *outlen, int flag, int *errno)
628 626 {
629 627 return (kiconvstr_to_sb(KICONV_TBLID_850, (uchar_t *)inarray,
630 628 inlen, (uchar_t *)outarray, outlen, flag, errno));
631 629 }
632 630
633 631 /*
634 632 * The following is the common kiconvstr function for conversions from
635 633 * single byte codesets to UTF-8.
636 634 */
637 635 static size_t
638 636 kiconvstr_fr_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
639 637 size_t *outlen, int flag, int *errno)
640 638 {
641 639 size_t ret_val;
642 640 uchar_t *ibtail;
643 641 uchar_t *obtail;
644 642 size_t i;
645 643 size_t k;
646 644 int8_t sz;
647 645 boolean_t do_not_ignore_null;
648 646
649 647 ret_val = 0;
650 648 ibtail = ib + *inlen;
651 649 obtail = ob + *outlen;
652 650 do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
653 651
654 652 while (ib < ibtail) {
655 653 if (*ib == '\0' && do_not_ignore_null)
656 654 break;
657 655
658 656 if (*ib < 0x80) {
659 657 if (ob >= obtail) {
660 658 *errno = E2BIG;
661 659 ret_val = (size_t)-1;
662 660 break;
663 661 }
664 662 *ob++ = *ib++;
665 663 continue;
666 664 }
667 665
668 666 k = *ib - 0x80;
669 667 sz = u8_number_of_bytes[to_u8_tbl[id][k].u8[0]];
670 668
671 669 if (sz <= 0) {
672 670 if (flag & KICONV_REPLACE_INVALID) {
673 671 if ((obtail - ob) < 3) {
674 672 *errno = E2BIG;
675 673 ret_val = (size_t)-1;
676 674 break;
677 675 }
678 676
679 677 /* Save KICONV_UTF8_REPLACEMENT_CHAR. */
680 678 *ob++ = 0xef;
681 679 *ob++ = 0xbf;
682 680 *ob++ = 0xbd;
683 681 ret_val++;
684 682 ib++;
685 683
686 684 continue;
687 685 }
688 686
689 687 *errno = EILSEQ;
690 688 ret_val = (size_t)-1;
691 689 break;
692 690 }
693 691
694 692 if ((obtail - ob) < sz) {
695 693 *errno = E2BIG;
696 694 ret_val = (size_t)-1;
697 695 break;
698 696 }
699 697
700 698 for (i = 0; i < sz; i++)
701 699 *ob++ = to_u8_tbl[id][k].u8[i];
702 700
703 701 ib++;
704 702 }
705 703
706 704 *inlen = ibtail - ib;
707 705 *outlen = obtail - ob;
708 706
709 707 return (ret_val);
710 708 }
711 709
712 710 /*
713 711 * The following four functions are also entry points recorded at
714 712 * the conv_list[] at below.
715 713 */
716 714 static size_t
717 715 kiconvstr_fr_1252(char *inarray, size_t *inlen, char *outarray,
718 716 size_t *outlen, int flag, int *errno)
719 717 {
720 718 return (kiconvstr_fr_sb(KICONV_TBLID_1252, (uchar_t *)inarray,
721 719 inlen, (uchar_t *)outarray, outlen, flag, errno));
722 720 }
723 721
724 722 static size_t
725 723 kiconvstr_fr_1(char *inarray, size_t *inlen, char *outarray,
726 724 size_t *outlen, int flag, int *errno)
727 725 {
728 726 return (kiconvstr_fr_sb(KICONV_TBLID_8859_1, (uchar_t *)inarray,
729 727 inlen, (uchar_t *)outarray, outlen, flag, errno));
730 728 }
731 729
732 730 static size_t
733 731 kiconvstr_fr_15(char *inarray, size_t *inlen, char *outarray,
734 732 size_t *outlen, int flag, int *errno)
735 733 {
736 734 return (kiconvstr_fr_sb(KICONV_TBLID_8859_15, (uchar_t *)inarray,
737 735 inlen, (uchar_t *)outarray, outlen, flag, errno));
738 736 }
739 737
740 738 static size_t
741 739 kiconvstr_fr_850(char *inarray, size_t *inlen, char *outarray,
742 740 size_t *outlen, int flag, int *errno)
743 741 {
744 742 return (kiconvstr_fr_sb(KICONV_TBLID_850, (uchar_t *)inarray,
745 743 inlen, (uchar_t *)outarray, outlen, flag, errno));
746 744 }
747 745
748 746 /*
749 747 * The following static vector contains the normalized code names
750 748 * and their corresponding code ids. They are somewhat arbitrarily ordered
751 749 * based on marketing data available. A code id could repeat for aliases.
752 750 *
753 751 * The vector was generated by using a small utility program called
754 752 * codeidlistgen.c that you can find from PSARC/2007/173/materials/util/.
755 753 *
756 754 * The code ids must be portable, i.e., if needed, you can always generate
757 755 * the code_list[] again with different code ids. You'll also need to
758 756 * update the conv_list[] at below.
759 757 */
760 758 #define KICONV_MAX_CODEID_ENTRY 68
761 759 #define KICONV_MAX_CODEID 42
762 760
763 761 static kiconv_code_list_t code_list[KICONV_MAX_CODEID_ENTRY] = {
764 762 { "utf8", 0 },
765 763 { "cp1252", 1 },
766 764 { "1252", 1 },
767 765 { "iso88591", 2 },
768 766 { "iso885915", 3 },
769 767 { "cp850", 4 },
770 768 { "850", 4 },
771 769 { "eucjp", 5 },
772 770 { "eucjpms", 6 },
773 771 { "cp932", 7 },
774 772 { "932", 7 },
775 773 { "shiftjis", 8 },
776 774 { "pck", 8 },
777 775 { "sjis", 8 },
778 776 { "gb18030", 9 },
779 777 { "gbk", 10 },
780 778 { "cp936", 10 },
781 779 { "936", 10 },
782 780 { "euccn", 11 },
783 781 { "euckr", 12 },
784 782 { "unifiedhangul", 13 },
785 783 { "cp949", 13 },
786 784 { "949", 13 },
787 785 { "big5", 14 },
788 786 { "cp950", 14 },
789 787 { "950", 14 },
790 788 { "big5hkscs", 15 },
791 789 { "euctw", 16 },
792 790 { "cp950hkscs", 17 },
793 791 { "cp1250", 18 },
794 792 { "1250", 18 },
795 793 { "iso88592", 19 },
796 794 { "cp852", 20 },
797 795 { "852", 20 },
798 796 { "cp1251", 21 },
799 797 { "1251", 21 },
800 798 { "iso88595", 22 },
801 799 { "koi8r", 23 },
802 800 { "cp866", 24 },
803 801 { "866", 24 },
804 802 { "cp1253", 25 },
805 803 { "1253", 25 },
806 804 { "iso88597", 26 },
807 805 { "cp737", 27 },
808 806 { "737", 27 },
809 807 { "cp1254", 28 },
810 808 { "1254", 28 },
811 809 { "iso88599", 29 },
812 810 { "cp857", 30 },
813 811 { "857", 30 },
814 812 { "cp1256", 31 },
815 813 { "1256", 31 },
816 814 { "iso88596", 32 },
817 815 { "cp720", 33 },
818 816 { "720", 33 },
819 817 { "cp1255", 34 },
820 818 { "1255", 34 },
821 819 { "iso88598", 35 },
822 820 { "cp862", 36 },
823 821 { "862", 36 },
824 822 { "cp1257", 37 },
825 823 { "1257", 37 },
826 824 { "iso885913", 38 },
827 825 { "iso885910", 39 },
828 826 { "iso885911", 40 },
829 827 { "tis620", 40 },
830 828 { "iso88593", 41 },
831 829 { "iso88594", 42 },
832 830 };
833 831
834 832 /*
835 833 * The list of code conversions supported are grouped together per
836 834 * module which will be loaded as needed.
837 835 */
838 836 #define KICONV_MAX_CONVERSIONS 84
839 837
840 838 static kiconv_conv_list_t conv_list[KICONV_MAX_CONVERSIONS] = {
841 839 /* Embedded code conversions: */
842 840 {
843 841 1, 0, KICONV_EMBEDDED,
844 842 open_to_1252, kiconv_to_sb, close_to_sb, kiconvstr_to_1252
845 843 },
846 844 {
847 845 0, 1, KICONV_EMBEDDED,
848 846 open_fr_1252, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1252
849 847 },
850 848 {
851 849 2, 0, KICONV_EMBEDDED,
852 850 open_to_88591, kiconv_to_sb, close_to_sb, kiconvstr_to_1
853 851 },
854 852 {
855 853 0, 2, KICONV_EMBEDDED,
856 854 open_fr_88591, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1
857 855 },
858 856 {
859 857 3, 0, KICONV_EMBEDDED,
860 858 open_to_885915, kiconv_to_sb, close_to_sb, kiconvstr_to_15
861 859 },
862 860 {
863 861 0, 3, KICONV_EMBEDDED,
864 862 open_fr_885915, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_15
865 863 },
866 864 {
867 865 4, 0, KICONV_EMBEDDED,
868 866 open_to_850, kiconv_to_sb, close_to_sb, kiconvstr_to_850
869 867 },
870 868 {
871 869 0, 4, KICONV_EMBEDDED,
872 870 open_fr_850, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_850
873 871 },
874 872
875 873 /* kiconv_ja module conversions: */
876 874 { 0, 5, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
877 875 { 5, 0, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
878 876 { 0, 6, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
879 877 { 6, 0, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
880 878 { 0, 7, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
881 879 { 7, 0, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
882 880 { 0, 8, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
883 881 { 8, 0, KICONV_MODULE_ID_JA, NULL, NULL, NULL, NULL },
884 882
885 883 /* kiconv_sc module conversions: */
886 884 { 0, 9, KICONV_MODULE_ID_SC, NULL, NULL, NULL, NULL },
887 885 { 9, 0, KICONV_MODULE_ID_SC, NULL, NULL, NULL, NULL },
888 886 { 0, 10, KICONV_MODULE_ID_SC, NULL, NULL, NULL, NULL },
889 887 { 10, 0, KICONV_MODULE_ID_SC, NULL, NULL, NULL, NULL },
890 888 { 0, 11, KICONV_MODULE_ID_SC, NULL, NULL, NULL, NULL },
891 889 { 11, 0, KICONV_MODULE_ID_SC, NULL, NULL, NULL, NULL },
892 890
893 891 /* kiconv_ko module conversions: */
894 892 { 0, 12, KICONV_MODULE_ID_KO, NULL, NULL, NULL, NULL },
895 893 { 12, 0, KICONV_MODULE_ID_KO, NULL, NULL, NULL, NULL },
896 894 { 0, 13, KICONV_MODULE_ID_KO, NULL, NULL, NULL, NULL },
897 895 { 13, 0, KICONV_MODULE_ID_KO, NULL, NULL, NULL, NULL },
898 896
899 897 /* kiconv_tc module conversions: */
900 898 { 0, 14, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
901 899 { 14, 0, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
902 900 { 0, 15, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
903 901 { 15, 0, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
904 902 { 0, 16, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
905 903 { 16, 0, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
906 904 { 0, 17, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
907 905 { 17, 0, KICONV_MODULE_ID_TC, NULL, NULL, NULL, NULL },
908 906
909 907 /* kiconv_emea module conversions: */
910 908 { 0, 18, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
911 909 { 18, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
912 910 { 0, 19, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
913 911 { 19, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
914 912 { 0, 20, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
915 913 { 20, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
916 914 { 0, 21, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
917 915 { 21, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
918 916 { 0, 22, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
919 917 { 22, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
920 918 { 0, 23, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
921 919 { 23, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
922 920 { 0, 24, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
923 921 { 24, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
924 922 { 0, 25, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
925 923 { 25, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
926 924 { 0, 26, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
927 925 { 26, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
928 926 { 0, 27, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
929 927 { 27, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
930 928 { 0, 28, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
931 929 { 28, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
932 930 { 0, 29, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
933 931 { 29, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
934 932 { 0, 30, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
935 933 { 30, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
936 934 { 0, 31, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
937 935 { 31, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
938 936 { 0, 32, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
939 937 { 32, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
940 938 { 0, 33, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
941 939 { 33, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
942 940 { 0, 34, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
943 941 { 34, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
944 942 { 0, 35, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
945 943 { 35, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
946 944 { 0, 36, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
947 945 { 36, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
948 946 { 0, 37, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
949 947 { 37, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
950 948 { 0, 38, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
951 949 { 38, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
952 950 { 0, 39, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
953 951 { 39, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
↓ open down ↓ |
916 lines elided |
↑ open up ↑ |
954 952 { 0, 40, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
955 953 { 40, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
956 954 { 0, 41, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
957 955 { 41, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
958 956 { 0, 42, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
959 957 { 42, 0, KICONV_MODULE_ID_EMEA, NULL, NULL, NULL, NULL },
960 958 };
961 959
962 960 /* The list of implemeted and supported modules. */
963 961 static kiconv_mod_list_t module_list[KICONV_MAX_MODULE_ID + 1] = {
964 - "kiconv_embedded", 0,
965 - "kiconv_ja", 0,
966 - "kiconv_sc", 0,
967 - "kiconv_ko", 0,
968 - "kiconv_tc", 0,
969 - "kiconv_emea", 0,
962 + { "kiconv_embedded", 0 },
963 + { "kiconv_ja", 0 },
964 + { "kiconv_sc", 0 },
965 + { "kiconv_ko", 0 },
966 + { "kiconv_tc", 0 },
967 + { "kiconv_emea", 0 }
970 968 };
971 969
972 970 /*
973 971 * We use conv_list_lock to restrict data access of both conv_list[] and
974 972 * module_list[] as they are tightly coupled critical sections that need to be
975 973 * dealt together as a unit.
976 974 */
977 975 static kmutex_t conv_list_lock;
978 976
979 977 void
980 978 kiconv_init()
981 979 {
982 980 mutex_init(&conv_list_lock, NULL, MUTEX_DEFAULT, NULL);
983 981 }
984 982
985 983 /*
986 984 * The following is used to check on whether a kiconv module is being
987 985 * used or not at the _fini() of the module.
988 986 */
989 987 size_t
990 988 kiconv_module_ref_count(size_t mid)
991 989 {
992 990 int count;
993 991
994 992 if (mid <= 0 || mid > KICONV_MAX_MODULE_ID)
995 993 return (0);
996 994
997 995 mutex_enter(&conv_list_lock);
998 996
999 997 count = module_list[mid].refcount;
1000 998
1001 999 mutex_exit(&conv_list_lock);
1002 1000
1003 1001 return (count);
1004 1002 }
1005 1003
1006 1004 /*
1007 1005 * This function "normalizes" a given code name, n, by not including skippable
1008 1006 * characters and folding uppercase letters to corresponding lowercase letters.
1009 1007 * We only fold 7-bit ASCII uppercase characters since the names should be in
1010 1008 * Portable Character Set of 7-bit ASCII.
1011 1009 *
1012 1010 * By doing this, we will be able to maximize the code name matches.
1013 1011 */
1014 1012 static size_t
1015 1013 normalize_codename(const char *n)
1016 1014 {
1017 1015 char s[KICONV_MAX_CODENAME_LEN + 1];
1018 1016 size_t i;
1019 1017
1020 1018 if (n == NULL)
1021 1019 return ((size_t)-1);
1022 1020
1023 1021 for (i = 0; *n; n++) {
1024 1022 if (KICONV_SKIPPABLE_CHAR(*n))
1025 1023 continue;
1026 1024
1027 1025 /* If unreasonably lengthy, we don't support such names. */
1028 1026 if (i >= KICONV_MAX_CODENAME_LEN)
1029 1027 return ((size_t)-1);
1030 1028
1031 1029 s[i++] = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
1032 1030 }
1033 1031 s[i] = '\0';
1034 1032
1035 1033 /* With the normalized name, find the corresponding codeset id. */
1036 1034 for (i = 0; i < KICONV_MAX_CODEID_ENTRY; i++)
1037 1035 if (strcmp(s, code_list[i].name) == 0)
1038 1036 return (code_list[i].id);
1039 1037
1040 1038 /*
1041 1039 * In future time, we will also have a few more lines of code at below
1042 1040 * that will deal with other user-created modules' fromcodes and
1043 1041 * tocodes including aliases in a different vector. For now, we don't
1044 1042 * support that but only the known names to this project at this time.
1045 1043 */
1046 1044
1047 1045 return ((size_t)-1);
1048 1046 }
1049 1047
1050 1048 /*
1051 1049 * This function called from mod_install() registers supplied code
1052 1050 * conversions. At this point, it does not honor aliases and hence does not
1053 1051 * use nowait data field from the kiconv module info data structure.
1054 1052 */
1055 1053 int
1056 1054 kiconv_register_module(kiconv_module_info_t *info)
1057 1055 {
1058 1056 size_t mid;
1059 1057 size_t fid;
1060 1058 size_t tid;
1061 1059 size_t i;
1062 1060 size_t j;
1063 1061 kiconv_ops_t *op;
1064 1062
1065 1063 /* Validate the given kiconv module info. */
1066 1064 if (info == NULL || info->module_name == NULL ||
1067 1065 info->kiconv_num_convs == 0 || info->kiconv_ops_tbl == NULL)
1068 1066 return (EINVAL);
1069 1067
1070 1068 /*
1071 1069 * Check if this is one of the known modules. At this point,
1072 1070 * we do not allow user-defined kiconv modules and that'd be for
1073 1071 * a future project.
1074 1072 */
1075 1073 for (mid = 1; mid <= KICONV_MAX_MODULE_ID; mid++)
1076 1074 if (strcmp(module_list[mid].name, info->module_name) == 0)
1077 1075 break;
1078 1076 if (mid > KICONV_MAX_MODULE_ID)
1079 1077 return (EINVAL);
1080 1078
1081 1079 /* Let's register the conversions supplied. */
1082 1080 mutex_enter(&conv_list_lock);
1083 1081
1084 1082 /*
1085 1083 * This is very unlikely situation but by any chance we don't want to
1086 1084 * register a module that is already in.
1087 1085 */
1088 1086 if (module_list[mid].refcount > 0) {
1089 1087 mutex_exit(&conv_list_lock);
1090 1088 return (EAGAIN);
1091 1089 }
1092 1090
1093 1091 for (i = 0; i < info->kiconv_num_convs; i++) {
1094 1092 op = &(info->kiconv_ops_tbl[i]);
1095 1093
1096 1094 fid = normalize_codename(op->fromcode);
1097 1095 tid = normalize_codename(op->tocode);
1098 1096
1099 1097 /*
1100 1098 * If we find anything wrong in this particular conversion,
1101 1099 * we skip this one and continue to the next one. This include
1102 1100 * a case where there is a conversion already being assigned
1103 1101 * into the conv_list[] somehow, i.e., new one never kicks out
1104 1102 * old one.
1105 1103 */
1106 1104 if (op->kiconv_open == NULL || op->kiconv == NULL ||
1107 1105 op->kiconv_close == NULL || op->kiconvstr == NULL)
1108 1106 continue;
1109 1107
1110 1108 for (j = 0; j < KICONV_MAX_CONVERSIONS; j++) {
1111 1109 if (conv_list[j].mid == mid &&
1112 1110 conv_list[j].fid == fid &&
1113 1111 conv_list[j].tid == tid) {
1114 1112 if (conv_list[j].open == NULL) {
1115 1113 conv_list[j].open = op->kiconv_open;
1116 1114 conv_list[j].kiconv = op->kiconv;
1117 1115 conv_list[j].close = op->kiconv_close;
1118 1116 conv_list[j].kiconvstr = op->kiconvstr;
1119 1117 }
1120 1118 break;
1121 1119 }
1122 1120 }
1123 1121 }
1124 1122
1125 1123 mutex_exit(&conv_list_lock);
1126 1124
1127 1125 return (0);
1128 1126 }
1129 1127
1130 1128 /*
1131 1129 * The following function called during mod_remove() will try to unregister,
1132 1130 * i.e., clear up conversion function pointers, from the conv_list[] if it
1133 1131 * can. If there is any code conversions being used, then, the function will
1134 1132 * just return EBUSY indicating that the module cannot be unloaded.
1135 1133 */
1136 1134 int
1137 1135 kiconv_unregister_module(kiconv_module_info_t *info)
1138 1136 {
1139 1137 size_t mid;
1140 1138 size_t i;
1141 1139
1142 1140 if (info == NULL || info->module_name == NULL ||
1143 1141 info->kiconv_num_convs == 0 || info->kiconv_ops_tbl == NULL)
1144 1142 return (EINVAL);
1145 1143
1146 1144 for (mid = 1; mid <= KICONV_MAX_MODULE_ID; mid++)
1147 1145 if (strcmp(module_list[mid].name, info->module_name) == 0)
1148 1146 break;
1149 1147 if (mid > KICONV_MAX_MODULE_ID)
1150 1148 return (EINVAL);
1151 1149
1152 1150 mutex_enter(&conv_list_lock);
1153 1151
1154 1152 /*
1155 1153 * If any of the conversions are used, then, this module canont be
1156 1154 * unloaded.
1157 1155 */
1158 1156 if (module_list[mid].refcount > 0) {
1159 1157 mutex_exit(&conv_list_lock);
1160 1158 return (EBUSY);
1161 1159 }
1162 1160
1163 1161 /*
1164 1162 * Otherwise, we unregister all conversions from this module
1165 1163 * and be ready for the unloading. At this point, we only care about
1166 1164 * the conversions we know about with the module.
1167 1165 */
1168 1166 for (i = 0; i < KICONV_MAX_CONVERSIONS; i++) {
1169 1167 if (conv_list[i].mid == mid) {
1170 1168 conv_list[i].open = NULL;
1171 1169 conv_list[i].kiconv = NULL;
1172 1170 conv_list[i].close = NULL;
1173 1171 conv_list[i].kiconvstr = NULL;
1174 1172 }
1175 1173 }
1176 1174
1177 1175 mutex_exit(&conv_list_lock);
1178 1176
1179 1177 return (0);
1180 1178 }
1181 1179
1182 1180 /*
1183 1181 * The following function check if asked code conversion is available
1184 1182 * and if necessary, load the corresponding kiconv module that contains
1185 1183 * the conversion (and others).
1186 1184 */
1187 1185 static kiconv_t
1188 1186 check_and_load_conversions(const char *tocode, const char *fromcode)
1189 1187 {
1190 1188 kiconv_t kcd;
1191 1189 size_t tid;
1192 1190 size_t fid;
1193 1191 size_t mid;
1194 1192 size_t i;
1195 1193
1196 1194 /* Normalize the given names and find the corresponding code ids. */
1197 1195 tid = normalize_codename(tocode);
1198 1196 if (tid == (size_t)-1)
1199 1197 return ((kiconv_t)-1);
1200 1198
1201 1199 fid = normalize_codename(fromcode);
1202 1200 if (fid == (size_t)-1)
1203 1201 return ((kiconv_t)-1);
1204 1202
1205 1203 /*
1206 1204 * Search the conversion.
1207 1205 *
1208 1206 * If the conversion isn't supported, just return -1.
1209 1207 * If the conversion is supported but there is no corresponding
1210 1208 * module loaded, try to load it and if successful, return
1211 1209 * a kiconv conversion descriptor memory block.
1212 1210 *
1213 1211 * We maintain a reference counter of uint_t for each module.
1214 1212 */
1215 1213 mutex_enter(&conv_list_lock);
1216 1214
1217 1215 for (i = 0; i < KICONV_MAX_CONVERSIONS; i++)
1218 1216 if (conv_list[i].tid == tid && conv_list[i].fid == fid)
1219 1217 break;
1220 1218 if (i >= KICONV_MAX_CONVERSIONS) {
1221 1219 mutex_exit(&conv_list_lock);
1222 1220 return ((kiconv_t)-1);
1223 1221 }
1224 1222
1225 1223 mid = conv_list[i].mid;
1226 1224
1227 1225 if (conv_list[i].open == NULL) {
1228 1226 mutex_exit(&conv_list_lock);
1229 1227
1230 1228 if (modload("kiconv", module_list[mid].name) < 0)
1231 1229 return ((kiconv_t)-1);
1232 1230
1233 1231 /*
1234 1232 * Let's double check if something happened right after
1235 1233 * the modload and/or if the module really has the conversion.
1236 1234 */
1237 1235 mutex_enter(&conv_list_lock);
1238 1236
1239 1237 if (conv_list[i].open == NULL) {
1240 1238 mutex_exit(&conv_list_lock);
1241 1239 return ((kiconv_t)-1);
1242 1240 }
1243 1241 }
1244 1242
1245 1243 /*
1246 1244 * If we got the conversion, we will use the conversion function
1247 1245 * in the module and so let's increase the module's refcounter
1248 1246 * so that the module won't be kicked out. (To be more exact and
1249 1247 * specific, the "refcount" is thus the reference counter of
1250 1248 * the module functions being used.)
1251 1249 */
1252 1250 if (module_list[mid].refcount < UINT_MAX)
1253 1251 module_list[mid].refcount++;
1254 1252
1255 1253 mutex_exit(&conv_list_lock);
1256 1254
1257 1255 kcd = (kiconv_t)kmem_alloc(sizeof (kiconv_data_t), KM_SLEEP);
1258 1256 kcd->handle = (void *)-1;
1259 1257 kcd->id = i;
1260 1258
1261 1259 return (kcd);
1262 1260 }
1263 1261
1264 1262 /*
1265 1263 * The following are the four "Committed" interfaces.
1266 1264 */
1267 1265 kiconv_t
1268 1266 kiconv_open(const char *tocode, const char *fromcode)
1269 1267 {
1270 1268 kiconv_t kcd;
1271 1269 size_t mid;
1272 1270
1273 1271 kcd = check_and_load_conversions(tocode, fromcode);
1274 1272 if (kcd == (kiconv_t)-1)
1275 1273 return ((kiconv_t)-1);
1276 1274
1277 1275 kcd->handle = (conv_list[kcd->id].open)();
1278 1276 if (kcd->handle == (void *)-1) {
1279 1277 /*
1280 1278 * If the conversion couldn't be opened for some reason,
1281 1279 * then, we unallocate the kcd and, more importantly, before
1282 1280 * that, we also decrease the module reference counter.
1283 1281 */
1284 1282 mid = conv_list[kcd->id].mid;
1285 1283
1286 1284 mutex_enter(&conv_list_lock);
1287 1285
1288 1286 if (module_list[mid].refcount > 0)
1289 1287 module_list[mid].refcount--;
1290 1288
1291 1289 mutex_exit(&conv_list_lock);
1292 1290
1293 1291 kmem_free((void *)kcd, sizeof (kiconv_data_t));
1294 1292
1295 1293 return ((kiconv_t)-1);
1296 1294 }
1297 1295
1298 1296 return (kcd);
1299 1297 }
1300 1298
1301 1299 size_t
1302 1300 kiconv(kiconv_t kcd, char **inbuf, size_t *inbytesleft,
1303 1301 char **outbuf, size_t *outbytesleft, int *errno)
1304 1302 {
1305 1303 /* Do some minimum checking on the kiconv conversion descriptor. */
1306 1304 if (! kcd || kcd == (kiconv_t)-1 || conv_list[kcd->id].kiconv == NULL) {
1307 1305 *errno = EBADF;
1308 1306 return ((size_t)-1);
1309 1307 }
1310 1308
1311 1309 return ((conv_list[kcd->id].kiconv)(kcd->handle, inbuf, inbytesleft,
1312 1310 outbuf, outbytesleft, errno));
1313 1311 }
1314 1312
1315 1313 int
1316 1314 kiconv_close(kiconv_t kcd)
1317 1315 {
1318 1316 int ret;
1319 1317 size_t mid;
1320 1318
1321 1319 if (! kcd || kcd == (kiconv_t)-1 || conv_list[kcd->id].close == NULL)
1322 1320 return (EBADF);
1323 1321
1324 1322 mid = conv_list[kcd->id].mid;
1325 1323
1326 1324 ret = (conv_list[kcd->id].close)(kcd->handle);
1327 1325
1328 1326 kmem_free((void *)kcd, sizeof (kiconv_data_t));
1329 1327
1330 1328 mutex_enter(&conv_list_lock);
1331 1329
1332 1330 /*
1333 1331 * While we maintain reference conter for each module, once loaded,
1334 1332 * we don't modunload from kiconv functions even if the counter
1335 1333 * reaches back to zero.
1336 1334 */
1337 1335 if (module_list[mid].refcount > 0)
1338 1336 module_list[mid].refcount--;
1339 1337
1340 1338 mutex_exit(&conv_list_lock);
1341 1339
1342 1340 return (ret);
1343 1341 }
1344 1342
1345 1343 size_t
1346 1344 kiconvstr(const char *tocode, const char *fromcode, char *inarray,
1347 1345 size_t *inlen, char *outarray, size_t *outlen, int flag, int *errno)
1348 1346 {
1349 1347 kiconv_t kcd;
1350 1348 size_t ret;
1351 1349 size_t mid;
1352 1350
1353 1351 kcd = check_and_load_conversions(tocode, fromcode);
1354 1352 if (kcd == (kiconv_t)-1 || conv_list[kcd->id].kiconvstr == NULL) {
1355 1353 *errno = EBADF;
1356 1354 return ((size_t)-1);
1357 1355 }
1358 1356
1359 1357 mid = conv_list[kcd->id].mid;
1360 1358
1361 1359 ret = (conv_list[kcd->id].kiconvstr)(inarray, inlen, outarray, outlen,
1362 1360 flag, errno);
1363 1361
1364 1362 kmem_free((void *)kcd, sizeof (kiconv_data_t));
1365 1363
1366 1364 mutex_enter(&conv_list_lock);
1367 1365
1368 1366 if (module_list[mid].refcount > 0)
1369 1367 module_list[mid].refcount--;
1370 1368
1371 1369 mutex_exit(&conv_list_lock);
1372 1370
1373 1371 return (ret);
1374 1372 }
↓ open down ↓ |
395 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX