1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #pragma ident   "%Z%%M% %I%     %E% SMI"
  27 
  28 /*
  29  * Kernel iconv code conversion module (kiconv_emea) for Europe, Middle East,
  30  * and South East Asia (PSARC/2007/173).
  31  */
  32 
  33 #include <sys/types.h>
  34 #include <sys/param.h>
  35 #include <sys/sysmacros.h>
  36 #include <sys/systm.h>
  37 #include <sys/debug.h>
  38 #include <sys/kmem.h>
  39 #include <sys/cmn_err.h>
  40 #include <sys/ddi.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/ksynch.h>
  43 #include <sys/modctl.h>
  44 #include <sys/byteorder.h>
  45 #include <sys/errno.h>
  46 #include <sys/kiconv.h>
  47 #include <sys/kiconv_emea1.h>
  48 #include <sys/kiconv_emea2.h>
  49 
  50 
  51 /*
  52  * The following macros indicate ids to the correct code conversion mapping
  53  * data tables to use. The actual tables are coming from <sys/kiconv_emea1.h>
  54  * and <sys/kiconv_emea2.h>. If you update the header files, then, you might
  55  * also need to update the table ids at below.
  56  *
  57  * The table for KICONV_TBLID_720 is a special case and should come from
  58  * a separate header file than others at <sys/kiconv_emea1.h> hence it has
  59  * an id that is rather unusual distinguishing itself from others. (And,
  60  * the ids much be of uint8_t.)
  61  */
  62 #define KICONV_TBLID_720                (0xFFU)
  63 #define KICONV_TBLID_RANGE1_START       KICONV_TBLID_720
  64 #define KICONV_TBLID_RANGE1_END         KICONV_TBLID_720
  65 
  66 #define KICONV_TBLID_737                (0)
  67 #define KICONV_TBLID_852                (1)
  68 #define KICONV_TBLID_857                (2)
  69 #define KICONV_TBLID_862                (3)
  70 #define KICONV_TBLID_866                (4)
  71 #define KICONV_TBLID_1250               (5)
  72 #define KICONV_TBLID_1251               (6)
  73 #define KICONV_TBLID_1253               (7)
  74 #define KICONV_TBLID_1254               (8)
  75 #define KICONV_TBLID_1255               (9)
  76 #define KICONV_TBLID_1256               (10)
  77 #define KICONV_TBLID_1257               (11)
  78 #define KICONV_TBLID_8859_2             (12)
  79 #define KICONV_TBLID_8859_3             (13)
  80 #define KICONV_TBLID_8859_4             (14)
  81 #define KICONV_TBLID_8859_5             (15)
  82 #define KICONV_TBLID_8859_6             (16)
  83 #define KICONV_TBLID_8859_7             (17)
  84 #define KICONV_TBLID_8859_8             (18)
  85 #define KICONV_TBLID_8859_9             (19)
  86 #define KICONV_TBLID_8859_10            (20)
  87 #define KICONV_TBLID_8859_11            (21)
  88 #define KICONV_TBLID_8859_13            (22)
  89 #define KICONV_TBLID_KOI8_R             (23)
  90 
  91 #define KICONV_MAX_MAPPING_TBLID        KICONV_TBLID_KOI8_R
  92 
  93 /*
  94  * The following tables are coming from u8_textprep.c. We use them to
  95  * check on validity of UTF-8 characters and their bytes.
  96  */
  97 extern const int8_t u8_number_of_bytes[];
  98 extern const uint8_t u8_valid_min_2nd_byte[];
  99 extern const uint8_t u8_valid_max_2nd_byte[];
 100 
 101 
 102 /*
 103  * The following 25 open_to_xxxx() functions are kiconv_open functions for
 104  * the conversions from UTF-8 to xxxx single byte codesets.
 105  */
 106 static void *
 107 open_to_720()
 108 {
 109         kiconv_state_t s;
 110 
 111         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 112         s->id = KICONV_TBLID_720;
 113         s->bom_processed = 0;
 114 
 115         return ((void *)s);
 116 }
 117 
 118 static void *
 119 open_to_737()
 120 {
 121         kiconv_state_t s;
 122 
 123         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 124         s->id = KICONV_TBLID_737;
 125         s->bom_processed = 0;
 126 
 127         return ((void *)s);
 128 }
 129 
 130 static void *
 131 open_to_852()
 132 {
 133         kiconv_state_t s;
 134 
 135         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 136         s->id = KICONV_TBLID_852;
 137         s->bom_processed = 0;
 138 
 139         return ((void *)s);
 140 }
 141 
 142 static void *
 143 open_to_857()
 144 {
 145         kiconv_state_t s;
 146 
 147         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 148         s->id = KICONV_TBLID_857;
 149         s->bom_processed = 0;
 150 
 151         return ((void *)s);
 152 }
 153 
 154 static void *
 155 open_to_862()
 156 {
 157         kiconv_state_t s;
 158 
 159         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 160         s->id = KICONV_TBLID_862;
 161         s->bom_processed = 0;
 162 
 163         return ((void *)s);
 164 }
 165 
 166 static void *
 167 open_to_866()
 168 {
 169         kiconv_state_t s;
 170 
 171         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 172         s->id = KICONV_TBLID_866;
 173         s->bom_processed = 0;
 174 
 175         return ((void *)s);
 176 }
 177 
 178 static void *
 179 open_to_1250()
 180 {
 181         kiconv_state_t s;
 182 
 183         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 184         s->id = KICONV_TBLID_1250;
 185         s->bom_processed = 0;
 186 
 187         return ((void *)s);
 188 }
 189 
 190 static void *
 191 open_to_1251()
 192 {
 193         kiconv_state_t s;
 194 
 195         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 196         s->id = KICONV_TBLID_1251;
 197         s->bom_processed = 0;
 198 
 199         return ((void *)s);
 200 }
 201 
 202 static void *
 203 open_to_1253()
 204 {
 205         kiconv_state_t s;
 206 
 207         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 208         s->id = KICONV_TBLID_1253;
 209         s->bom_processed = 0;
 210 
 211         return ((void *)s);
 212 }
 213 
 214 static void *
 215 open_to_1254()
 216 {
 217         kiconv_state_t s;
 218 
 219         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 220         s->id = KICONV_TBLID_1254;
 221         s->bom_processed = 0;
 222 
 223         return ((void *)s);
 224 }
 225 
 226 static void *
 227 open_to_1255()
 228 {
 229         kiconv_state_t s;
 230 
 231         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 232         s->id = KICONV_TBLID_1255;
 233         s->bom_processed = 0;
 234 
 235         return ((void *)s);
 236 }
 237 
 238 static void *
 239 open_to_1256()
 240 {
 241         kiconv_state_t s;
 242 
 243         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 244         s->id = KICONV_TBLID_1256;
 245         s->bom_processed = 0;
 246 
 247         return ((void *)s);
 248 }
 249 
 250 static void *
 251 open_to_1257()
 252 {
 253         kiconv_state_t s;
 254 
 255         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 256         s->id = KICONV_TBLID_1257;
 257         s->bom_processed = 0;
 258 
 259         return ((void *)s);
 260 }
 261 
 262 static void *
 263 open_to_88592()
 264 {
 265         kiconv_state_t s;
 266 
 267         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 268         s->id = KICONV_TBLID_8859_2;
 269         s->bom_processed = 0;
 270 
 271         return ((void *)s);
 272 }
 273 
 274 static void *
 275 open_to_88593()
 276 {
 277         kiconv_state_t s;
 278 
 279         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 280         s->id = KICONV_TBLID_8859_3;
 281         s->bom_processed = 0;
 282 
 283         return ((void *)s);
 284 }
 285 
 286 static void *
 287 open_to_88594()
 288 {
 289         kiconv_state_t s;
 290 
 291         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 292         s->id = KICONV_TBLID_8859_4;
 293         s->bom_processed = 0;
 294 
 295         return ((void *)s);
 296 }
 297 
 298 static void *
 299 open_to_88595()
 300 {
 301         kiconv_state_t s;
 302 
 303         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 304         s->id = KICONV_TBLID_8859_5;
 305         s->bom_processed = 0;
 306 
 307         return ((void *)s);
 308 }
 309 
 310 static void *
 311 open_to_88596()
 312 {
 313         kiconv_state_t s;
 314 
 315         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 316         s->id = KICONV_TBLID_8859_6;
 317         s->bom_processed = 0;
 318 
 319         return ((void *)s);
 320 }
 321 
 322 static void *
 323 open_to_88597()
 324 {
 325         kiconv_state_t s;
 326 
 327         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 328         s->id = KICONV_TBLID_8859_7;
 329         s->bom_processed = 0;
 330 
 331         return ((void *)s);
 332 }
 333 
 334 static void *
 335 open_to_88598()
 336 {
 337         kiconv_state_t s;
 338 
 339         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 340         s->id = KICONV_TBLID_8859_8;
 341         s->bom_processed = 0;
 342 
 343         return ((void *)s);
 344 }
 345 
 346 static void *
 347 open_to_88599()
 348 {
 349         kiconv_state_t s;
 350 
 351         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 352         s->id = KICONV_TBLID_8859_9;
 353         s->bom_processed = 0;
 354 
 355         return ((void *)s);
 356 }
 357 
 358 static void *
 359 open_to_885910()
 360 {
 361         kiconv_state_t s;
 362 
 363         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 364         s->id = KICONV_TBLID_8859_10;
 365         s->bom_processed = 0;
 366 
 367         return ((void *)s);
 368 }
 369 
 370 static void *
 371 open_to_885911()
 372 {
 373         kiconv_state_t s;
 374 
 375         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 376         s->id = KICONV_TBLID_8859_11;
 377         s->bom_processed = 0;
 378 
 379         return ((void *)s);
 380 }
 381 
 382 static void *
 383 open_to_885913()
 384 {
 385         kiconv_state_t s;
 386 
 387         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 388         s->id = KICONV_TBLID_8859_13;
 389         s->bom_processed = 0;
 390 
 391         return ((void *)s);
 392 }
 393 
 394 static void *
 395 open_to_koi8r()
 396 {
 397         kiconv_state_t s;
 398 
 399         s = (kiconv_state_t)kmem_alloc(sizeof (kiconv_state_data_t), KM_SLEEP);
 400         s->id = KICONV_TBLID_KOI8_R;
 401         s->bom_processed = 0;
 402 
 403         return ((void *)s);
 404 }
 405 
 406 /*
 407  * The following 25 open_fr_xxxx() functions are kiconv_open functions for
 408  * the conversions from xxxx single byte codeset to UTF-8.
 409  */
 410 static void *
 411 open_fr_720()
 412 {
 413         return ((void *)KICONV_TBLID_720);
 414 }
 415 
 416 static void *
 417 open_fr_737()
 418 {
 419         return ((void *)KICONV_TBLID_737);
 420 }
 421 
 422 static void *
 423 open_fr_852()
 424 {
 425         return ((void *)KICONV_TBLID_852);
 426 }
 427 
 428 static void *
 429 open_fr_857()
 430 {
 431         return ((void *)KICONV_TBLID_857);
 432 }
 433 
 434 static void *
 435 open_fr_862()
 436 {
 437         return ((void *)KICONV_TBLID_862);
 438 }
 439 
 440 static void *
 441 open_fr_866()
 442 {
 443         return ((void *)KICONV_TBLID_866);
 444 }
 445 
 446 static void *
 447 open_fr_1250()
 448 {
 449         return ((void *)KICONV_TBLID_1250);
 450 }
 451 
 452 static void *
 453 open_fr_1251()
 454 {
 455         return ((void *)KICONV_TBLID_1251);
 456 }
 457 
 458 static void *
 459 open_fr_1253()
 460 {
 461         return ((void *)KICONV_TBLID_1253);
 462 }
 463 
 464 static void *
 465 open_fr_1254()
 466 {
 467         return ((void *)KICONV_TBLID_1254);
 468 }
 469 
 470 static void *
 471 open_fr_1255()
 472 {
 473         return ((void *)KICONV_TBLID_1255);
 474 }
 475 
 476 static void *
 477 open_fr_1256()
 478 {
 479         return ((void *)KICONV_TBLID_1256);
 480 }
 481 
 482 static void *
 483 open_fr_1257()
 484 {
 485         return ((void *)KICONV_TBLID_1257);
 486 }
 487 
 488 static void *
 489 open_fr_88592()
 490 {
 491         return ((void *)KICONV_TBLID_8859_2);
 492 }
 493 
 494 static void *
 495 open_fr_88593()
 496 {
 497         return ((void *)KICONV_TBLID_8859_3);
 498 }
 499 
 500 static void *
 501 open_fr_88594()
 502 {
 503         return ((void *)KICONV_TBLID_8859_4);
 504 }
 505 
 506 static void *
 507 open_fr_88595()
 508 {
 509         return ((void *)KICONV_TBLID_8859_5);
 510 }
 511 
 512 static void *
 513 open_fr_88596()
 514 {
 515         return ((void *)KICONV_TBLID_8859_6);
 516 }
 517 
 518 static void *
 519 open_fr_88597()
 520 {
 521         return ((void *)KICONV_TBLID_8859_7);
 522 }
 523 
 524 static void *
 525 open_fr_88598()
 526 {
 527         return ((void *)KICONV_TBLID_8859_8);
 528 }
 529 
 530 static void *
 531 open_fr_88599()
 532 {
 533         return ((void *)KICONV_TBLID_8859_9);
 534 }
 535 
 536 static void *
 537 open_fr_885910()
 538 {
 539         return ((void *)KICONV_TBLID_8859_10);
 540 }
 541 
 542 static void *
 543 open_fr_885911()
 544 {
 545         return ((void *)KICONV_TBLID_8859_11);
 546 }
 547 
 548 static void *
 549 open_fr_885913()
 550 {
 551         return ((void *)KICONV_TBLID_8859_13);
 552 }
 553 
 554 static void *
 555 open_fr_koi8r()
 556 {
 557         return ((void *)KICONV_TBLID_KOI8_R);
 558 }
 559 
 560 /*
 561  * The following is the common kiconv_close function for the conversions from
 562  * UTF-8 to single byte codesets.
 563  */
 564 static int
 565 close_to_sb(void *s)
 566 {
 567         if (! s || s == (void *)-1)
 568                 return (EBADF);
 569 
 570         kmem_free(s, sizeof (kiconv_state_data_t));
 571 
 572         return (0);
 573 }
 574 
 575 /*
 576  * The following is the common kiconv_close function for the conversions from
 577  * single byte codesets to UTF-8.
 578  */
 579 static int
 580 close_fr_sb(void *s)
 581 {
 582         if ((ulong_t)s > KICONV_MAX_MAPPING_TBLID &&
 583             ((ulong_t)s < KICONV_TBLID_RANGE1_START ||
 584             (ulong_t)s > KICONV_TBLID_RANGE1_END))
 585                 return (EBADF);
 586 
 587         return (0);
 588 }
 589 
 590 /*
 591  * The following is the common kiconv function for the conversions from
 592  * UTF-8 to single byte codesets. (This may look a lot similar to
 593  * kiconvstr_to_sb() but they do have different features to cover and
 594  * it's not really worth to try to merge them into a single function since
 595  * you'll have to add performance penalty for both per each character
 596  * conversion as you will have to figure out if this is kiconv_to_sb() or
 597  * kiconvstr_to_sb().)
 598  */
 599 static size_t
 600 kiconv_to_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
 601         size_t *outbytesleft, int *errno)
 602 {
 603         kiconv_to_sb_tbl_comp_t *tbl;
 604         size_t id;
 605         size_t ret_val;
 606         uchar_t *ib;
 607         uchar_t *oldib;
 608         uchar_t *ob;
 609         uchar_t *ibtail;
 610         uchar_t *obtail;
 611         uint32_t u8;
 612         size_t i;
 613         size_t l;
 614         size_t h;
 615         size_t init_h;
 616         int8_t sz;
 617         boolean_t second;
 618 
 619         /* Check on the kiconv code conversion descriptor. */
 620         if (! kcd || kcd == (void *)-1) {
 621                 *errno = EBADF;
 622                 return ((size_t)-1);
 623         }
 624 
 625         /* Get the table id and check on it. */
 626         id = ((kiconv_state_t)kcd)->id;
 627         if (id > KICONV_MAX_MAPPING_TBLID &&
 628             (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
 629                 *errno = EBADF;
 630                 return ((size_t)-1);
 631         }
 632 
 633         /* If this is a state reset request, process and return. */
 634         if (! inbuf || ! (*inbuf)) {
 635                 ((kiconv_state_t)kcd)->bom_processed = 0;
 636                 return ((size_t)0);
 637         }
 638 
 639         ret_val = 0;
 640         ib = (uchar_t *)*inbuf;
 641         ob = (uchar_t *)*outbuf;
 642         ibtail = ib + *inbytesleft;
 643         obtail = ob + *outbytesleft;
 644 
 645         /*
 646          * Get the table we want to use and also calculate the "init_h"
 647          * which is the initial high index for the binary search that we will
 648          * use. While the table sizes are all the same at the moment, to be
 649          * ready for future cases where tables could be in different sizes,
 650          * we separately calculate the init_h at here.
 651          */
 652         if (id == KICONV_TBLID_720) {
 653                 tbl = (kiconv_to_sb_tbl_comp_t *)u8_to_cp720_tbl;
 654                 init_h = sizeof (u8_to_cp720_tbl);
 655         } else {
 656                 tbl = (kiconv_to_sb_tbl_comp_t *)to_sb_tbl[id];
 657                 init_h = sizeof (to_sb_tbl[id]);
 658         }
 659         init_h = init_h / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
 660 
 661         /*
 662          * If we haven't checked on the UTF-8 signature BOM character in
 663          * the beginning of the conversion data stream, we check it and if
 664          * find one, we skip it since we have no use for it.
 665          */
 666         if (((kiconv_state_t)kcd)->bom_processed == 0 && (ibtail - ib) >= 3 &&
 667             *ib == 0xef && *(ib + 1) == 0xbb && *(ib + 2) == 0xbf)
 668                         ib += 3;
 669         ((kiconv_state_t)kcd)->bom_processed = 1;
 670 
 671         while (ib < ibtail) {
 672                 sz = u8_number_of_bytes[*ib];
 673                 if (sz <= 0) {
 674                         *errno = EILSEQ;
 675                         ret_val = (size_t)-1;
 676                         break;
 677                 }
 678 
 679                 /*
 680                  * If there is no room to write at the output buffer,
 681                  * we issue E2BIG and let the caller knows about it.
 682                  */
 683                 if (ob >= obtail) {
 684                         *errno = E2BIG;
 685                         ret_val = (size_t)-1;
 686                         break;
 687                 }
 688 
 689                 /*
 690                  * If it is a 7-bit ASCII character, we don't need to
 691                  * process further and we just copy the character over.
 692                  *
 693                  * If not, we collect the character bytes up to four bytes,
 694                  * validate the bytes, and binary search for the corresponding
 695                  * single byte codeset character byte. If we find it from
 696                  * the mapping table, we put that into the output buffer;
 697                  * otherwise, we put a replacement character instead as
 698                  * a non-identical conversion.
 699                  */
 700                 if (sz == 1) {
 701                         *ob++ = *ib++;
 702                         continue;
 703                 }
 704 
 705                 /*
 706                  * Issue EINVAL if the last character at the input buffer
 707                  * is an incomplete character missing a byte or more.
 708                  */
 709                 if ((ibtail - ib) < sz) {
 710                         *errno = EINVAL;
 711                         ret_val = (size_t)-1;
 712                         break;
 713                 }
 714 
 715                 /*
 716                  * We collect UTF-8 character bytes and at the same time,
 717                  * check on if the bytes are valid bytes or not. This follows
 718                  * the latest UTF-8 byte representation.
 719                  */
 720                 oldib = ib;
 721                 u8 = *ib++;
 722                 second = B_TRUE;
 723                 for (i = 1; i < sz; i++) {
 724                         if (second) {
 725                                 if (*ib < u8_valid_min_2nd_byte[u8] ||
 726                                     *ib > u8_valid_max_2nd_byte[u8]) {
 727                                         *errno = EILSEQ;
 728                                         ret_val = (size_t)-1;
 729                                         ib = oldib;
 730                                         goto TO_SB_ILLEGAL_CHAR_ERR;
 731                                 }
 732                                 second = B_FALSE;
 733                         } else if (*ib < 0x80 || *ib > 0xbf) {
 734                                 *errno = EILSEQ;
 735                                 ret_val = (size_t)-1;
 736                                 ib = oldib;
 737                                 goto TO_SB_ILLEGAL_CHAR_ERR;
 738                         }
 739                         u8 = (u8 << 8) | ((uint32_t)*ib);
 740                         ib++;
 741                 }
 742 
 743                 i = l = 0;
 744                 h = init_h;
 745                 while (l <= h) {
 746                         i = (l + h) / 2;
 747                         if (tbl[i].u8 == u8)
 748                                 break;
 749                         else if (tbl[i].u8 < u8)
 750                                 l = i + 1;
 751                         else
 752                                 h = i - 1;
 753                 }
 754 
 755                 if (tbl[i].u8 == u8) {
 756                         *ob++ = tbl[i].sb;
 757                 } else {
 758                         /*
 759                          * What this means is that we encountered
 760                          * a non-identical conversion. In other words,
 761                          * input buffer contains a valid character in
 762                          * the fromcode but the tocode doesn't have
 763                          * any character that can be mapped to.
 764                          *
 765                          * In this case, we insert an ASCII replacement
 766                          * character instead at the output buffer and
 767                          * count such non-identical conversions by
 768                          * increasing the ret_val.
 769                          *
 770                          * If the return value of the function is bigger
 771                          * than zero, that means we had such non-identical
 772                          * conversion(s).
 773                          */
 774                         *ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
 775                         ret_val++;
 776                 }
 777         }
 778 
 779 TO_SB_ILLEGAL_CHAR_ERR:
 780         *inbuf = (char *)ib;
 781         *inbytesleft = ibtail - ib;
 782         *outbuf = (char *)ob;
 783         *outbytesleft = obtail - ob;
 784 
 785         return (ret_val);
 786 }
 787 
 788 /*
 789  * The following is the common kiconv function for the conversions from
 790  * single byte codesets to UTf-8.
 791  */
 792 static size_t
 793 kiconv_fr_sb(void *kcd, char **inbuf, size_t *inbytesleft, char **outbuf,
 794         size_t *outbytesleft, int *errno)
 795 {
 796         kiconv_to_utf8_tbl_comp_t *tbl;
 797         size_t ret_val;
 798         uchar_t *ib;
 799         uchar_t *ob;
 800         uchar_t *ibtail;
 801         uchar_t *obtail;
 802         size_t i;
 803         size_t k;
 804         int8_t sz;
 805 
 806         /* Validate the kiconv code conversion descriptor. */
 807         if ((ulong_t)kcd > KICONV_MAX_MAPPING_TBLID &&
 808             ((ulong_t)kcd < KICONV_TBLID_RANGE1_START ||
 809             (ulong_t)kcd > KICONV_TBLID_RANGE1_END)) {
 810                 *errno = EBADF;
 811                 return ((size_t)-1);
 812         }
 813 
 814         /*
 815          * If this is a state reset request, there is nothing to do and so
 816          * we just return.
 817          */
 818         if (! inbuf || ! (*inbuf))
 819                 return ((size_t)0);
 820 
 821         ret_val = 0;
 822         ib = (uchar_t *)*inbuf;
 823         ob = (uchar_t *)*outbuf;
 824         ibtail = ib + *inbytesleft;
 825         obtail = ob + *outbytesleft;
 826 
 827         tbl = ((ulong_t)kcd == KICONV_TBLID_720) ?
 828             (kiconv_to_utf8_tbl_comp_t *)cp720_to_u8_tbl :
 829             (kiconv_to_utf8_tbl_comp_t *)to_u8_tbl[(ulong_t)kcd];
 830 
 831         while (ib < ibtail) {
 832                 /*
 833                  * If this is a 7-bit ASCII character, we just copy over and
 834                  * that's all we need to do for this character.
 835                  */
 836                 if (*ib < 0x80) {
 837                         if (ob >= obtail) {
 838                                 *errno = E2BIG;
 839                                 ret_val = (size_t)-1;
 840                                 break;
 841                         }
 842 
 843                         *ob++ = *ib++;
 844                         continue;
 845                 }
 846 
 847                 /*
 848                  * Otherwise, we get the corresponding UTF-8 character bytes
 849                  * from the mapping table and copy them over.
 850                  *
 851                  * We don't need to worry about if the UTF-8 character bytes
 852                  * at the mapping tables are valid or not since they are good.
 853                  */
 854                 k = *ib - 0x80;
 855                 sz = u8_number_of_bytes[tbl[k].u8[0]];
 856 
 857                 /*
 858                  * If (sz <= 0), that means the character in the input buffer
 859                  * is an illegal character possibly unassigned or non-character
 860                  * at the fromcode single byte codeset.
 861                  */
 862                 if (sz <= 0) {
 863                         *errno = EILSEQ;
 864                         ret_val = (size_t)-1;
 865                         break;
 866                 }
 867 
 868                 if ((obtail - ob) < sz) {
 869                         *errno = E2BIG;
 870                         ret_val = (size_t)-1;
 871                         break;
 872                 }
 873 
 874                 for (i = 0; i < sz; i++)
 875                         *ob++ = tbl[k].u8[i];
 876 
 877                 ib++;
 878         }
 879 
 880         *inbuf = (char *)ib;
 881         *inbytesleft = ibtail - ib;
 882         *outbuf = (char *)ob;
 883         *outbytesleft = obtail - ob;
 884 
 885         return (ret_val);
 886 }
 887 
 888 /*
 889  * The following is the common kiconvstr function for the conversions from
 890  * UTF-8 to single byte codeset.
 891  */
 892 static size_t
 893 kiconvstr_to_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
 894         size_t *outlen, int flag, int *errno)
 895 {
 896         kiconv_to_sb_tbl_comp_t *tbl;
 897         size_t ret_val;
 898         uchar_t *oldib;
 899         uchar_t *ibtail;
 900         uchar_t *obtail;
 901         uint32_t u8;
 902         size_t i;
 903         size_t l;
 904         size_t h;
 905         size_t init_h;
 906         int8_t sz;
 907         boolean_t second;
 908         boolean_t do_not_ignore_null;
 909 
 910         /* Let's double check on the table id. */
 911         if (id > KICONV_MAX_MAPPING_TBLID &&
 912             (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
 913                 *errno = EBADF;
 914                 return ((size_t)-1);
 915         }
 916 
 917         ret_val = 0;
 918         ibtail = ib + *inlen;
 919         obtail = ob + *outlen;
 920         do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
 921 
 922         if (id == KICONV_TBLID_720) {
 923                 tbl = (kiconv_to_sb_tbl_comp_t *)u8_to_cp720_tbl;
 924                 init_h = sizeof (u8_to_cp720_tbl);
 925         } else {
 926                 tbl = (kiconv_to_sb_tbl_comp_t *)to_sb_tbl[id];
 927                 init_h = sizeof (to_sb_tbl[id]);
 928         }
 929         init_h = init_h / sizeof (kiconv_to_sb_tbl_comp_t) - 1;
 930 
 931         /* Skip any UTF-8 signature BOM character in the beginning. */
 932         if ((ibtail - ib) >= 3 && *ib == 0xef && *(ib + 1) == 0xbb &&
 933             *(ib + 2) == 0xbf)
 934                         ib += 3;
 935 
 936         /*
 937          * Basically this is pretty much the same as kiconv_to_sb() except
 938          * that we are now accepting two flag values and doing the processing
 939          * accordingly.
 940          */
 941         while (ib < ibtail) {
 942                 sz = u8_number_of_bytes[*ib];
 943                 if (sz <= 0) {
 944                         if (flag & KICONV_REPLACE_INVALID) {
 945                                 if (ob >= obtail) {
 946                                         *errno = E2BIG;
 947                                         ret_val = (size_t)-1;
 948                                         break;
 949                                 }
 950 
 951                                 ib++;
 952                                 goto STR_TO_SB_REPLACE_INVALID;
 953                         }
 954 
 955                         *errno = EILSEQ;
 956                         ret_val = (size_t)-1;
 957                         break;
 958                 }
 959 
 960                 if (*ib == '\0' && do_not_ignore_null)
 961                         break;
 962 
 963                 if (ob >= obtail) {
 964                         *errno = E2BIG;
 965                         ret_val = (size_t)-1;
 966                         break;
 967                 }
 968 
 969                 if (sz == 1) {
 970                         *ob++ = *ib++;
 971                         continue;
 972                 }
 973 
 974                 if ((ibtail - ib) < sz) {
 975                         if (flag & KICONV_REPLACE_INVALID) {
 976                                 ib = ibtail;
 977                                 goto STR_TO_SB_REPLACE_INVALID;
 978                         }
 979 
 980                         *errno = EINVAL;
 981                         ret_val = (size_t)-1;
 982                         break;
 983                 }
 984 
 985                 oldib = ib;
 986                 u8 = *ib++;
 987                 second = B_TRUE;
 988                 for (i = 1; i < sz; i++) {
 989                         if (second) {
 990                                 if (*ib < u8_valid_min_2nd_byte[u8] ||
 991                                     *ib > u8_valid_max_2nd_byte[u8]) {
 992                                         if (flag & KICONV_REPLACE_INVALID) {
 993                                                 ib = oldib + sz;
 994                                                 goto STR_TO_SB_REPLACE_INVALID;
 995                                         }
 996 
 997                                         *errno = EILSEQ;
 998                                         ret_val = (size_t)-1;
 999                                         ib = oldib;
1000                                         goto STR_TO_SB_ILLEGAL_CHAR_ERR;
1001                                 }
1002                                 second = B_FALSE;
1003                         } else if (*ib < 0x80 || *ib > 0xbf) {
1004                                 if (flag & KICONV_REPLACE_INVALID) {
1005                                         ib = oldib + sz;
1006                                         goto STR_TO_SB_REPLACE_INVALID;
1007                                 }
1008 
1009                                 *errno = EILSEQ;
1010                                 ret_val = (size_t)-1;
1011                                 ib = oldib;
1012                                 goto STR_TO_SB_ILLEGAL_CHAR_ERR;
1013                         }
1014                         u8 = (u8 << 8) | ((uint32_t)*ib);
1015                         ib++;
1016                 }
1017 
1018                 i = l = 0;
1019                 h = init_h;
1020                 while (l <= h) {
1021                         i = (l + h) / 2;
1022                         if (tbl[i].u8 == u8)
1023                                 break;
1024                         else if (tbl[i].u8 < u8)
1025                                 l = i + 1;
1026                         else
1027                                 h = i - 1;
1028                 }
1029 
1030                 if (tbl[i].u8 == u8) {
1031                         *ob++ = tbl[i].sb;
1032                 } else {
1033 STR_TO_SB_REPLACE_INVALID:
1034                         *ob++ = KICONV_ASCII_REPLACEMENT_CHAR;
1035                         ret_val++;
1036                 }
1037         }
1038 
1039 STR_TO_SB_ILLEGAL_CHAR_ERR:
1040         *inlen = ibtail - ib;
1041         *outlen = obtail - ob;
1042 
1043         return (ret_val);
1044 }
1045 
1046 /*
1047  * The following 25 functions are the real entry points that will be
1048  * given to the kiconv framework at the genunix.
1049  */
1050 static size_t
1051 kiconvstr_to_720(char *inarray, size_t *inlen, char *outarray,
1052         size_t *outlen, int flag, int *errno)
1053 {
1054         return (kiconvstr_to_sb(KICONV_TBLID_720, (uchar_t *)inarray,
1055             inlen, (uchar_t *)outarray, outlen, flag, errno));
1056 }
1057 
1058 static size_t
1059 kiconvstr_to_737(char *inarray, size_t *inlen, char *outarray,
1060         size_t *outlen, int flag, int *errno)
1061 {
1062         return (kiconvstr_to_sb(KICONV_TBLID_737, (uchar_t *)inarray,
1063             inlen, (uchar_t *)outarray, outlen, flag, errno));
1064 }
1065 
1066 static size_t
1067 kiconvstr_to_852(char *inarray, size_t *inlen, char *outarray,
1068         size_t *outlen, int flag, int *errno)
1069 {
1070         return (kiconvstr_to_sb(KICONV_TBLID_852, (uchar_t *)inarray,
1071             inlen, (uchar_t *)outarray, outlen, flag, errno));
1072 }
1073 
1074 static size_t
1075 kiconvstr_to_857(char *inarray, size_t *inlen, char *outarray,
1076         size_t *outlen, int flag, int *errno)
1077 {
1078         return (kiconvstr_to_sb(KICONV_TBLID_857, (uchar_t *)inarray,
1079             inlen, (uchar_t *)outarray, outlen, flag, errno));
1080 }
1081 
1082 static size_t
1083 kiconvstr_to_862(char *inarray, size_t *inlen, char *outarray,
1084         size_t *outlen, int flag, int *errno)
1085 {
1086         return (kiconvstr_to_sb(KICONV_TBLID_862, (uchar_t *)inarray,
1087             inlen, (uchar_t *)outarray, outlen, flag, errno));
1088 }
1089 
1090 static size_t
1091 kiconvstr_to_866(char *inarray, size_t *inlen, char *outarray,
1092         size_t *outlen, int flag, int *errno)
1093 {
1094         return (kiconvstr_to_sb(KICONV_TBLID_866, (uchar_t *)inarray,
1095             inlen, (uchar_t *)outarray, outlen, flag, errno));
1096 }
1097 
1098 static size_t
1099 kiconvstr_to_1250(char *inarray, size_t *inlen, char *outarray,
1100         size_t *outlen, int flag, int *errno)
1101 {
1102         return (kiconvstr_to_sb(KICONV_TBLID_1250, (uchar_t *)inarray,
1103             inlen, (uchar_t *)outarray, outlen, flag, errno));
1104 }
1105 
1106 static size_t
1107 kiconvstr_to_1251(char *inarray, size_t *inlen, char *outarray,
1108         size_t *outlen, int flag, int *errno)
1109 {
1110         return (kiconvstr_to_sb(KICONV_TBLID_1251, (uchar_t *)inarray,
1111             inlen, (uchar_t *)outarray, outlen, flag, errno));
1112 }
1113 
1114 static size_t
1115 kiconvstr_to_1253(char *inarray, size_t *inlen, char *outarray,
1116         size_t *outlen, int flag, int *errno)
1117 {
1118         return (kiconvstr_to_sb(KICONV_TBLID_1253, (uchar_t *)inarray,
1119             inlen, (uchar_t *)outarray, outlen, flag, errno));
1120 }
1121 
1122 static size_t
1123 kiconvstr_to_1254(char *inarray, size_t *inlen, char *outarray,
1124         size_t *outlen, int flag, int *errno)
1125 {
1126         return (kiconvstr_to_sb(KICONV_TBLID_1254, (uchar_t *)inarray,
1127             inlen, (uchar_t *)outarray, outlen, flag, errno));
1128 }
1129 
1130 static size_t
1131 kiconvstr_to_1255(char *inarray, size_t *inlen, char *outarray,
1132         size_t *outlen, int flag, int *errno)
1133 {
1134         return (kiconvstr_to_sb(KICONV_TBLID_1255, (uchar_t *)inarray,
1135             inlen, (uchar_t *)outarray, outlen, flag, errno));
1136 }
1137 
1138 static size_t
1139 kiconvstr_to_1256(char *inarray, size_t *inlen, char *outarray,
1140         size_t *outlen, int flag, int *errno)
1141 {
1142         return (kiconvstr_to_sb(KICONV_TBLID_1256, (uchar_t *)inarray,
1143             inlen, (uchar_t *)outarray, outlen, flag, errno));
1144 }
1145 
1146 static size_t
1147 kiconvstr_to_1257(char *inarray, size_t *inlen, char *outarray,
1148         size_t *outlen, int flag, int *errno)
1149 {
1150         return (kiconvstr_to_sb(KICONV_TBLID_1257, (uchar_t *)inarray,
1151             inlen, (uchar_t *)outarray, outlen, flag, errno));
1152 }
1153 
1154 static size_t
1155 kiconvstr_to_88592(char *inarray, size_t *inlen, char *outarray,
1156         size_t *outlen, int flag, int *errno)
1157 {
1158         return (kiconvstr_to_sb(KICONV_TBLID_8859_2, (uchar_t *)inarray,
1159             inlen, (uchar_t *)outarray, outlen, flag, errno));
1160 }
1161 
1162 static size_t
1163 kiconvstr_to_88593(char *inarray, size_t *inlen, char *outarray,
1164         size_t *outlen, int flag, int *errno)
1165 {
1166         return (kiconvstr_to_sb(KICONV_TBLID_8859_3, (uchar_t *)inarray,
1167             inlen, (uchar_t *)outarray, outlen, flag, errno));
1168 }
1169 
1170 static size_t
1171 kiconvstr_to_88594(char *inarray, size_t *inlen, char *outarray,
1172         size_t *outlen, int flag, int *errno)
1173 {
1174         return (kiconvstr_to_sb(KICONV_TBLID_8859_4, (uchar_t *)inarray,
1175             inlen, (uchar_t *)outarray, outlen, flag, errno));
1176 }
1177 
1178 static size_t
1179 kiconvstr_to_88595(char *inarray, size_t *inlen, char *outarray,
1180         size_t *outlen, int flag, int *errno)
1181 {
1182         return (kiconvstr_to_sb(KICONV_TBLID_8859_5, (uchar_t *)inarray,
1183             inlen, (uchar_t *)outarray, outlen, flag, errno));
1184 }
1185 
1186 static size_t
1187 kiconvstr_to_88596(char *inarray, size_t *inlen, char *outarray,
1188         size_t *outlen, int flag, int *errno)
1189 {
1190         return (kiconvstr_to_sb(KICONV_TBLID_8859_6, (uchar_t *)inarray,
1191             inlen, (uchar_t *)outarray, outlen, flag, errno));
1192 }
1193 
1194 static size_t
1195 kiconvstr_to_88597(char *inarray, size_t *inlen, char *outarray,
1196         size_t *outlen, int flag, int *errno)
1197 {
1198         return (kiconvstr_to_sb(KICONV_TBLID_8859_7, (uchar_t *)inarray,
1199             inlen, (uchar_t *)outarray, outlen, flag, errno));
1200 }
1201 
1202 static size_t
1203 kiconvstr_to_88598(char *inarray, size_t *inlen, char *outarray,
1204         size_t *outlen, int flag, int *errno)
1205 {
1206         return (kiconvstr_to_sb(KICONV_TBLID_8859_8, (uchar_t *)inarray,
1207             inlen, (uchar_t *)outarray, outlen, flag, errno));
1208 }
1209 
1210 static size_t
1211 kiconvstr_to_88599(char *inarray, size_t *inlen, char *outarray,
1212         size_t *outlen, int flag, int *errno)
1213 {
1214         return (kiconvstr_to_sb(KICONV_TBLID_8859_9, (uchar_t *)inarray,
1215             inlen, (uchar_t *)outarray, outlen, flag, errno));
1216 }
1217 
1218 static size_t
1219 kiconvstr_to_885910(char *inarray, size_t *inlen, char *outarray,
1220         size_t *outlen, int flag, int *errno)
1221 {
1222         return (kiconvstr_to_sb(KICONV_TBLID_8859_10, (uchar_t *)inarray,
1223             inlen, (uchar_t *)outarray, outlen, flag, errno));
1224 }
1225 
1226 static size_t
1227 kiconvstr_to_885911(char *inarray, size_t *inlen, char *outarray,
1228         size_t *outlen, int flag, int *errno)
1229 {
1230         return (kiconvstr_to_sb(KICONV_TBLID_8859_11, (uchar_t *)inarray,
1231             inlen, (uchar_t *)outarray, outlen, flag, errno));
1232 }
1233 
1234 static size_t
1235 kiconvstr_to_885913(char *inarray, size_t *inlen, char *outarray,
1236         size_t *outlen, int flag, int *errno)
1237 {
1238         return (kiconvstr_to_sb(KICONV_TBLID_8859_13, (uchar_t *)inarray,
1239             inlen, (uchar_t *)outarray, outlen, flag, errno));
1240 }
1241 
1242 static size_t
1243 kiconvstr_to_koi8r(char *inarray, size_t *inlen, char *outarray,
1244         size_t *outlen, int flag, int *errno)
1245 {
1246         return (kiconvstr_to_sb(KICONV_TBLID_KOI8_R, (uchar_t *)inarray,
1247             inlen, (uchar_t *)outarray, outlen, flag, errno));
1248 }
1249 
1250 /*
1251  * The following is the common kiconvstr function for the conversions from
1252  * single byte codeset to UTF-8.
1253  */
1254 static size_t
1255 kiconvstr_fr_sb(size_t id, uchar_t *ib, size_t *inlen, uchar_t *ob,
1256         size_t *outlen, int flag, int *errno)
1257 {
1258         kiconv_to_utf8_tbl_comp_t *tbl;
1259         size_t ret_val;
1260         uchar_t *ibtail;
1261         uchar_t *obtail;
1262         size_t i;
1263         size_t k;
1264         int8_t sz;
1265         boolean_t do_not_ignore_null;
1266 
1267         if (id > KICONV_MAX_MAPPING_TBLID &&
1268             (id < KICONV_TBLID_RANGE1_START || id > KICONV_TBLID_RANGE1_END)) {
1269                 *errno = EBADF;
1270                 return ((size_t)-1);
1271         }
1272 
1273         ret_val = 0;
1274         ibtail = ib + *inlen;
1275         obtail = ob + *outlen;
1276         do_not_ignore_null = ((flag & KICONV_IGNORE_NULL) == 0);
1277 
1278         tbl = (id == KICONV_TBLID_720) ?
1279             (kiconv_to_utf8_tbl_comp_t *)cp720_to_u8_tbl :
1280             (kiconv_to_utf8_tbl_comp_t *)to_u8_tbl[id];
1281 
1282         while (ib < ibtail) {
1283                 if (*ib == '\0' && do_not_ignore_null)
1284                         break;
1285 
1286                 if (*ib < 0x80) {
1287                         if (ob >= obtail) {
1288                                 *errno = E2BIG;
1289                                 ret_val = (size_t)-1;
1290                                 break;
1291                         }
1292                         *ob++ = *ib++;
1293                         continue;
1294                 }
1295 
1296                 k = *ib - 0x80;
1297                 sz = u8_number_of_bytes[tbl[k].u8[0]];
1298 
1299                 if (sz <= 0) {
1300                         if (flag & KICONV_REPLACE_INVALID) {
1301                                 if ((obtail - ob) < 3) {
1302                                         *errno = E2BIG;
1303                                         ret_val = (size_t)-1;
1304                                         break;
1305                                 }
1306 
1307                                 /* Save KICONV_UTF8_REPLACEMENT_CHAR. */
1308                                 *ob++ = 0xef;
1309                                 *ob++ = 0xbf;
1310                                 *ob++ = 0xbd;
1311                                 ret_val++;
1312                                 ib++;
1313 
1314                                 continue;
1315                         }
1316 
1317                         *errno = EILSEQ;
1318                         ret_val = (size_t)-1;
1319                         break;
1320                 }
1321 
1322                 if ((obtail - ob) < sz) {
1323                         *errno = E2BIG;
1324                         ret_val = (size_t)-1;
1325                         break;
1326                 }
1327 
1328                 for (i = 0; i < sz; i++)
1329                         *ob++ = tbl[k].u8[i];
1330 
1331                 ib++;
1332         }
1333 
1334         *inlen = ibtail - ib;
1335         *outlen = obtail - ob;
1336 
1337         return (ret_val);
1338 }
1339 
1340 /*
1341  * The following 25 functions are the real entry points that will be
1342  * given to kiconv framework at the genunix.
1343  */
1344 static size_t
1345 kiconvstr_fr_720(char *inarray, size_t *inlen, char *outarray,
1346         size_t *outlen, int flag, int *errno)
1347 {
1348         return (kiconvstr_fr_sb(KICONV_TBLID_720, (uchar_t *)inarray,
1349             inlen, (uchar_t *)outarray, outlen, flag, errno));
1350 }
1351 
1352 static size_t
1353 kiconvstr_fr_737(char *inarray, size_t *inlen, char *outarray,
1354         size_t *outlen, int flag, int *errno)
1355 {
1356         return (kiconvstr_fr_sb(KICONV_TBLID_737, (uchar_t *)inarray,
1357             inlen, (uchar_t *)outarray, outlen, flag, errno));
1358 }
1359 
1360 static size_t
1361 kiconvstr_fr_852(char *inarray, size_t *inlen, char *outarray,
1362         size_t *outlen, int flag, int *errno)
1363 {
1364         return (kiconvstr_fr_sb(KICONV_TBLID_852, (uchar_t *)inarray,
1365             inlen, (uchar_t *)outarray, outlen, flag, errno));
1366 }
1367 
1368 static size_t
1369 kiconvstr_fr_857(char *inarray, size_t *inlen, char *outarray,
1370         size_t *outlen, int flag, int *errno)
1371 {
1372         return (kiconvstr_fr_sb(KICONV_TBLID_857, (uchar_t *)inarray,
1373             inlen, (uchar_t *)outarray, outlen, flag, errno));
1374 }
1375 
1376 static size_t
1377 kiconvstr_fr_862(char *inarray, size_t *inlen, char *outarray,
1378         size_t *outlen, int flag, int *errno)
1379 {
1380         return (kiconvstr_fr_sb(KICONV_TBLID_862, (uchar_t *)inarray,
1381             inlen, (uchar_t *)outarray, outlen, flag, errno));
1382 }
1383 
1384 static size_t
1385 kiconvstr_fr_866(char *inarray, size_t *inlen, char *outarray,
1386         size_t *outlen, int flag, int *errno)
1387 {
1388         return (kiconvstr_fr_sb(KICONV_TBLID_866, (uchar_t *)inarray,
1389             inlen, (uchar_t *)outarray, outlen, flag, errno));
1390 }
1391 
1392 static size_t
1393 kiconvstr_fr_1250(char *inarray, size_t *inlen, char *outarray,
1394         size_t *outlen, int flag, int *errno)
1395 {
1396         return (kiconvstr_fr_sb(KICONV_TBLID_1250, (uchar_t *)inarray,
1397             inlen, (uchar_t *)outarray, outlen, flag, errno));
1398 }
1399 
1400 static size_t
1401 kiconvstr_fr_1251(char *inarray, size_t *inlen, char *outarray,
1402         size_t *outlen, int flag, int *errno)
1403 {
1404         return (kiconvstr_fr_sb(KICONV_TBLID_1251, (uchar_t *)inarray,
1405             inlen, (uchar_t *)outarray, outlen, flag, errno));
1406 }
1407 
1408 static size_t
1409 kiconvstr_fr_1253(char *inarray, size_t *inlen, char *outarray,
1410         size_t *outlen, int flag, int *errno)
1411 {
1412         return (kiconvstr_fr_sb(KICONV_TBLID_1253, (uchar_t *)inarray,
1413             inlen, (uchar_t *)outarray, outlen, flag, errno));
1414 }
1415 
1416 static size_t
1417 kiconvstr_fr_1254(char *inarray, size_t *inlen, char *outarray,
1418         size_t *outlen, int flag, int *errno)
1419 {
1420         return (kiconvstr_fr_sb(KICONV_TBLID_1254, (uchar_t *)inarray,
1421             inlen, (uchar_t *)outarray, outlen, flag, errno));
1422 }
1423 
1424 static size_t
1425 kiconvstr_fr_1255(char *inarray, size_t *inlen, char *outarray,
1426         size_t *outlen, int flag, int *errno)
1427 {
1428         return (kiconvstr_fr_sb(KICONV_TBLID_1255, (uchar_t *)inarray,
1429             inlen, (uchar_t *)outarray, outlen, flag, errno));
1430 }
1431 
1432 static size_t
1433 kiconvstr_fr_1256(char *inarray, size_t *inlen, char *outarray,
1434         size_t *outlen, int flag, int *errno)
1435 {
1436         return (kiconvstr_fr_sb(KICONV_TBLID_1256, (uchar_t *)inarray,
1437             inlen, (uchar_t *)outarray, outlen, flag, errno));
1438 }
1439 
1440 static size_t
1441 kiconvstr_fr_1257(char *inarray, size_t *inlen, char *outarray,
1442         size_t *outlen, int flag, int *errno)
1443 {
1444         return (kiconvstr_fr_sb(KICONV_TBLID_1257, (uchar_t *)inarray,
1445             inlen, (uchar_t *)outarray, outlen, flag, errno));
1446 }
1447 
1448 static size_t
1449 kiconvstr_fr_88592(char *inarray, size_t *inlen, char *outarray,
1450         size_t *outlen, int flag, int *errno)
1451 {
1452         return (kiconvstr_fr_sb(KICONV_TBLID_8859_2, (uchar_t *)inarray,
1453             inlen, (uchar_t *)outarray, outlen, flag, errno));
1454 }
1455 
1456 static size_t
1457 kiconvstr_fr_88593(char *inarray, size_t *inlen, char *outarray,
1458         size_t *outlen, int flag, int *errno)
1459 {
1460         return (kiconvstr_fr_sb(KICONV_TBLID_8859_3, (uchar_t *)inarray,
1461             inlen, (uchar_t *)outarray, outlen, flag, errno));
1462 }
1463 
1464 static size_t
1465 kiconvstr_fr_88594(char *inarray, size_t *inlen, char *outarray,
1466         size_t *outlen, int flag, int *errno)
1467 {
1468         return (kiconvstr_fr_sb(KICONV_TBLID_8859_4, (uchar_t *)inarray,
1469             inlen, (uchar_t *)outarray, outlen, flag, errno));
1470 }
1471 
1472 static size_t
1473 kiconvstr_fr_88595(char *inarray, size_t *inlen, char *outarray,
1474         size_t *outlen, int flag, int *errno)
1475 {
1476         return (kiconvstr_fr_sb(KICONV_TBLID_8859_5, (uchar_t *)inarray,
1477             inlen, (uchar_t *)outarray, outlen, flag, errno));
1478 }
1479 
1480 static size_t
1481 kiconvstr_fr_88596(char *inarray, size_t *inlen, char *outarray,
1482         size_t *outlen, int flag, int *errno)
1483 {
1484         return (kiconvstr_fr_sb(KICONV_TBLID_8859_6, (uchar_t *)inarray,
1485             inlen, (uchar_t *)outarray, outlen, flag, errno));
1486 }
1487 
1488 static size_t
1489 kiconvstr_fr_88597(char *inarray, size_t *inlen, char *outarray,
1490         size_t *outlen, int flag, int *errno)
1491 {
1492         return (kiconvstr_fr_sb(KICONV_TBLID_8859_7, (uchar_t *)inarray,
1493             inlen, (uchar_t *)outarray, outlen, flag, errno));
1494 }
1495 
1496 static size_t
1497 kiconvstr_fr_88598(char *inarray, size_t *inlen, char *outarray,
1498         size_t *outlen, int flag, int *errno)
1499 {
1500         return (kiconvstr_fr_sb(KICONV_TBLID_8859_8, (uchar_t *)inarray,
1501             inlen, (uchar_t *)outarray, outlen, flag, errno));
1502 }
1503 
1504 static size_t
1505 kiconvstr_fr_88599(char *inarray, size_t *inlen, char *outarray,
1506         size_t *outlen, int flag, int *errno)
1507 {
1508         return (kiconvstr_fr_sb(KICONV_TBLID_8859_9, (uchar_t *)inarray,
1509             inlen, (uchar_t *)outarray, outlen, flag, errno));
1510 }
1511 
1512 static size_t
1513 kiconvstr_fr_885910(char *inarray, size_t *inlen, char *outarray,
1514         size_t *outlen, int flag, int *errno)
1515 {
1516         return (kiconvstr_fr_sb(KICONV_TBLID_8859_10, (uchar_t *)inarray,
1517             inlen, (uchar_t *)outarray, outlen, flag, errno));
1518 }
1519 
1520 static size_t
1521 kiconvstr_fr_885911(char *inarray, size_t *inlen, char *outarray,
1522         size_t *outlen, int flag, int *errno)
1523 {
1524         return (kiconvstr_fr_sb(KICONV_TBLID_8859_11, (uchar_t *)inarray,
1525             inlen, (uchar_t *)outarray, outlen, flag, errno));
1526 }
1527 
1528 static size_t
1529 kiconvstr_fr_885913(char *inarray, size_t *inlen, char *outarray,
1530         size_t *outlen, int flag, int *errno)
1531 {
1532         return (kiconvstr_fr_sb(KICONV_TBLID_8859_13, (uchar_t *)inarray,
1533             inlen, (uchar_t *)outarray, outlen, flag, errno));
1534 }
1535 
1536 static size_t
1537 kiconvstr_fr_koi8r(char *inarray, size_t *inlen, char *outarray,
1538         size_t *outlen, int flag, int *errno)
1539 {
1540         return (kiconvstr_fr_sb(KICONV_TBLID_KOI8_R, (uchar_t *)inarray,
1541             inlen, (uchar_t *)outarray, outlen, flag, errno));
1542 }
1543 
1544 
1545 /*
1546  * The following are the supported code conversions that will be passed to
1547  * and registered from this module. The tocode and fromcode names are
1548  * normalized.
1549  */
1550 #define KICONV_MAX_EMEA_OPS             50
1551 
1552 static kiconv_ops_t kiconv_emea_ops[KICONV_MAX_EMEA_OPS] = {
1553         {
1554                 "utf8", "cp1250",
1555                 open_fr_1250, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1250
1556         },
1557         {
1558                 "cp1250", "utf8",
1559                 open_to_1250, kiconv_to_sb, close_to_sb, kiconvstr_to_1250
1560         },
1561         {
1562                 "utf8", "iso88592",
1563                 open_fr_88592, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88592
1564         },
1565         {
1566                 "iso88592", "utf8",
1567                 open_to_88592, kiconv_to_sb, close_to_sb, kiconvstr_to_88592
1568         },
1569         {
1570                 "utf8", "cp852",
1571                 open_fr_852, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_852
1572         },
1573         {
1574                 "cp852", "utf8",
1575                 open_to_852, kiconv_to_sb, close_to_sb, kiconvstr_to_852
1576         },
1577         {
1578                 "utf8", "cp1251",
1579                 open_fr_1251, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1251
1580         },
1581         {
1582                 "cp1251", "utf8",
1583                 open_to_1251, kiconv_to_sb, close_to_sb, kiconvstr_to_1251
1584         },
1585         {
1586                 "utf8", "iso88595",
1587                 open_fr_88595, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88595
1588         },
1589         {
1590                 "iso88595", "utf8",
1591                 open_to_88595, kiconv_to_sb, close_to_sb, kiconvstr_to_88595
1592         },
1593         {
1594                 "utf8", "koi8r",
1595                 open_fr_koi8r, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_koi8r
1596         },
1597         {
1598                 "koi8r", "utf8",
1599                 open_to_koi8r, kiconv_to_sb, close_to_sb, kiconvstr_to_koi8r
1600         },
1601         {
1602                 "utf8", "cp866",
1603                 open_fr_866, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_866
1604         },
1605         {
1606                 "cp866", "utf8",
1607                 open_to_866, kiconv_to_sb, close_to_sb, kiconvstr_to_866
1608         },
1609         {
1610                 "utf8", "cp1253",
1611                 open_fr_1253, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1253
1612         },
1613         {
1614                 "cp1253", "utf8",
1615                 open_to_1253, kiconv_to_sb, close_to_sb, kiconvstr_to_1253
1616         },
1617         {
1618                 "utf8", "iso88597",
1619                 open_fr_88597, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88597
1620         },
1621         {
1622                 "iso88597", "utf8",
1623                 open_to_88597, kiconv_to_sb, close_to_sb, kiconvstr_to_88597
1624         },
1625         {
1626                 "utf8", "cp737",
1627                 open_fr_737, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_737
1628         },
1629         {
1630                 "cp737", "utf8",
1631                 open_to_737, kiconv_to_sb, close_to_sb, kiconvstr_to_737
1632         },
1633         {
1634                 "utf8", "cp1254",
1635                 open_fr_1254, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1254
1636         },
1637         {
1638                 "cp1254", "utf8",
1639                 open_to_1254, kiconv_to_sb, close_to_sb, kiconvstr_to_1254
1640         },
1641         {
1642                 "utf8", "iso88599",
1643                 open_fr_88599, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88599
1644         },
1645         {
1646                 "iso88599", "utf8",
1647                 open_to_88599, kiconv_to_sb, close_to_sb, kiconvstr_to_88599
1648         },
1649         {
1650                 "utf8", "cp857",
1651                 open_fr_857, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_857
1652         },
1653         {
1654                 "cp857", "utf8",
1655                 open_to_857, kiconv_to_sb, close_to_sb, kiconvstr_to_857
1656         },
1657         {
1658                 "utf8", "cp1256",
1659                 open_fr_1256, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1256
1660         },
1661         {
1662                 "cp1256", "utf8",
1663                 open_to_1256, kiconv_to_sb, close_to_sb, kiconvstr_to_1256
1664         },
1665         {
1666                 "utf8", "iso88596",
1667                 open_fr_88596, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88596
1668         },
1669         {
1670                 "iso88596", "utf8",
1671                 open_to_88596, kiconv_to_sb, close_to_sb, kiconvstr_to_88596
1672         },
1673         {
1674                 "utf8", "cp720",
1675                 open_fr_720, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_720
1676         },
1677         {
1678                 "cp720", "utf8",
1679                 open_to_720, kiconv_to_sb, close_to_sb, kiconvstr_to_720
1680         },
1681         {
1682                 "utf8", "cp1255",
1683                 open_fr_1255, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1255
1684         },
1685         {
1686                 "cp1255", "utf8",
1687                 open_to_1255, kiconv_to_sb, close_to_sb, kiconvstr_to_1255
1688         },
1689         {
1690                 "utf8", "iso88598",
1691                 open_fr_88598, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88598
1692         },
1693         {
1694                 "iso88598", "utf8",
1695                 open_to_88598, kiconv_to_sb, close_to_sb, kiconvstr_to_88598
1696         },
1697         {
1698                 "utf8", "cp862",
1699                 open_fr_862, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_862
1700         },
1701         {
1702                 "cp862", "utf8",
1703                 open_to_862, kiconv_to_sb, close_to_sb, kiconvstr_to_862
1704         },
1705         {
1706                 "utf8", "cp1257",
1707                 open_fr_1257, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_1257
1708         },
1709         {
1710                 "cp1257", "utf8",
1711                 open_to_1257, kiconv_to_sb, close_to_sb, kiconvstr_to_1257
1712         },
1713         {
1714                 "utf8", "iso885913",
1715                 open_fr_885913, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885913
1716         },
1717         {
1718                 "iso885913", "utf8",
1719                 open_to_885913, kiconv_to_sb, close_to_sb, kiconvstr_to_885913
1720         },
1721         {
1722                 "utf8", "iso885910",
1723                 open_fr_885910, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885910
1724         },
1725         {
1726                 "iso885910", "utf8",
1727                 open_to_885910, kiconv_to_sb, close_to_sb, kiconvstr_to_885910
1728         },
1729         {
1730                 "utf8", "iso885911",
1731                 open_fr_885911, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_885911
1732         },
1733         {
1734                 "iso885911", "utf8",
1735                 open_to_885911, kiconv_to_sb, close_to_sb, kiconvstr_to_885911
1736         },
1737         {
1738                 "utf8", "iso88593",
1739                 open_fr_88593, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88593
1740         },
1741         {
1742                 "iso88593", "utf8",
1743                 open_to_88593, kiconv_to_sb, close_to_sb, kiconvstr_to_88593
1744         },
1745         {
1746                 "utf8", "iso88594",
1747                 open_fr_88594, kiconv_fr_sb, close_fr_sb, kiconvstr_fr_88594
1748         },
1749         {
1750                 "iso88594", "utf8",
1751                 open_to_88594, kiconv_to_sb, close_to_sb, kiconvstr_to_88594
1752         },
1753 };
1754 
1755 static kiconv_module_info_t kiconv_emea_modinfo = {
1756         "kiconv_emea",          /* Must be the same as in kiconv framework. */
1757         KICONV_MAX_EMEA_OPS,    /* size_t kiconv_num_convs */
1758         kiconv_emea_ops,        /* kiconv_ops_t *kiconv_ops_tbl */
1759         0,                      /* size_t kiconv_num_aliases */
1760         NULL,                   /* char **aliases */
1761         NULL,                   /* char **canonicals */
1762         0                       /* int nowait */
1763 };
1764 
1765 static struct modlkiconv kiconv_emea = {
1766         &mod_kiconvops,
1767         "kiconv module for EMEA",
1768         &kiconv_emea_modinfo
1769 };
1770 
1771 static struct modlinkage linkage = {
1772         MODREV_1,
1773         (void *)&kiconv_emea,
1774         NULL
1775 };
1776 
1777 int
1778 _init()
1779 {
1780         int err;
1781 
1782         err = mod_install(&linkage);
1783         if (err)
1784                 cmn_err(CE_WARN, "kiconv_emea: failed to load kernel module");
1785 
1786         return (err);
1787 }
1788 
1789 int
1790 _info(struct modinfo *modinfop)
1791 {
1792         return (mod_info(&linkage, modinfop));
1793 }
1794 
1795 int
1796 _fini()
1797 {
1798         int err;
1799 
1800         /*
1801          * If this module is being used, then, we cannot remove the module.
1802          * The following checking will catch pretty much all usual cases.
1803          *
1804          * Any remaining will be catached by the kiconv_unregister_module()
1805          * during mod_remove() at below.
1806          */
1807         if (kiconv_module_ref_count(KICONV_MODULE_ID_EMEA))
1808                 return (EBUSY);
1809 
1810         err = mod_remove(&linkage);
1811         if (err)
1812                 cmn_err(CE_WARN, "kiconv_emea: failed to remove kernel module");
1813 
1814         return (err);
1815 }