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