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