(root)/
glibc-2.38/
iconvdata/
tst-loading.c
       1  /* Tests for loading and unloading of iconv modules.
       2     Copyright (C) 2000-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <iconv.h>
      20  #include <mcheck.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  
      24  
      25  /* How many load/unload operations do we do.  */
      26  #define TEST_ROUNDS	5000
      27  
      28  
      29  enum state { unloaded, loaded };
      30  
      31  struct
      32  {
      33    const char *name;
      34    enum state state;
      35    iconv_t cd;
      36  } modules[] =
      37  {
      38  #define MODULE(Name) { .name = #Name, .state = unloaded }
      39    MODULE (ISO-8859-1),
      40    MODULE (ISO-8859-2),
      41    MODULE (ISO-8859-3),
      42    MODULE (ISO-8859-4),
      43    MODULE (ISO-8859-5),
      44    MODULE (ISO-8859-6),
      45    MODULE (ISO-8859-15),
      46    MODULE (EUC-JP),
      47    MODULE (EUC-KR),
      48    MODULE (EUC-CN),
      49    MODULE (EUC-TW),
      50    MODULE (SJIS),
      51    MODULE (UHC),
      52    MODULE (KOI8-R),
      53    MODULE (BIG5),
      54    MODULE (BIG5HKSCS)
      55  };
      56  #define nmodules (sizeof (modules) / sizeof (modules[0]))
      57  
      58  
      59  /* The test data.  */
      60  static const char inbuf[] =
      61  "The first step is the function to create a handle.\n"
      62  "\n"
      63  " - Function: iconv_t iconv_open (const char *TOCODE, const char\n"
      64  "          *FROMCODE)\n"
      65  "     The `iconv_open' function has to be used before starting a\n"
      66  "     conversion.  The two parameters this function takes determine the\n"
      67  "     source and destination character set for the conversion and if the\n"
      68  "     implementation has the possibility to perform such a conversion the\n"
      69  "     function returns a handle.\n"
      70  "\n"
      71  "     If the wanted conversion is not available the function returns\n"
      72  "     `(iconv_t) -1'.  In this case the global variable `errno' can have\n"
      73  "     the following values:\n"
      74  "\n"
      75  "    `EMFILE'\n"
      76  "          The process already has `OPEN_MAX' file descriptors open.\n"
      77  "\n"
      78  "    `ENFILE'\n"
      79  "          The system limit of open file is reached.\n"
      80  "\n"
      81  "    `ENOMEM'\n"
      82  "          Not enough memory to carry out the operation.\n"
      83  "\n"
      84  "    `EINVAL'\n"
      85  "          The conversion from FROMCODE to TOCODE is not supported.\n"
      86  "\n"
      87  "     It is not possible to use the same descriptor in different threads\n"
      88  "     to perform independent conversions.  Within the data structures\n"
      89  "     associated with the descriptor there is information about the\n"
      90  "     conversion state.  This must not be messed up by using it in\n"
      91  "     different conversions.\n"
      92  "\n"
      93  "     An `iconv' descriptor is like a file descriptor as for every use a\n"
      94  "     new descriptor must be created.  The descriptor does not stand for\n"
      95  "     all of the conversions from FROMSET to TOSET.\n"
      96  "\n"
      97  "     The GNU C library implementation of `iconv_open' has one\n"
      98  "     significant extension to other implementations.  To ease the\n"
      99  "     extension of the set of available conversions the implementation\n"
     100  "     allows storing the necessary files with data and code in\n"
     101  "     arbitrarily many directories.  How this extension has to be\n"
     102  "     written will be explained below (*note glibc iconv\n"
     103  "     Implementation::).  Here it is only important to say that all\n"
     104  "     directories mentioned in the `GCONV_PATH' environment variable are\n"
     105  "     considered if they contain a file `gconv-modules'.  These\n"
     106  "     directories need not necessarily be created by the system\n"
     107  "     administrator.  In fact, this extension is introduced to help users\n"
     108  "     writing and using their own, new conversions.  Of course this does\n"
     109  "     not work for security reasons in SUID binaries; in this case only\n"
     110  "     the system directory is considered and this normally is\n"
     111  "     `PREFIX/lib/gconv'.  The `GCONV_PATH' environment variable is\n"
     112  "     examined exactly once at the first call of the `iconv_open'\n"
     113  "     function.  Later modifications of the variable have no effect.\n";
     114  
     115  
     116  static int
     117  do_test (void)
     118  {
     119    size_t count = TEST_ROUNDS;
     120    int result = 0;
     121  
     122    mtrace ();
     123  
     124    /* Just a seed.  */
     125    srandom (TEST_ROUNDS);
     126  
     127    while (count--)
     128      {
     129        int idx = random () % nmodules;
     130  
     131        if (modules[idx].state == unloaded)
     132  	{
     133  	  char outbuf[10000];
     134  	  char *inptr = (char *) inbuf;
     135  	  size_t insize = sizeof (inbuf) - 1;
     136  	  char *outptr = outbuf;
     137  	  size_t outsize = sizeof (outbuf);
     138  
     139  	  /* Load the module and do the conversion.  */
     140  	  modules[idx].cd = iconv_open ("UTF-8", modules[idx].name);
     141  
     142  	  if (modules[idx].cd == (iconv_t) -1)
     143  	    {
     144  	      printf ("opening of %s failed: %m\n", modules[idx].name);
     145  	      result = 1;
     146  	      break;
     147  	    }
     148  
     149  	  modules[idx].state = loaded;
     150  
     151  	  /* Now a simple test.  */
     152  	  if (iconv (modules[idx].cd, &inptr, &insize, &outptr, &outsize) != 0
     153  	      || *inptr != '\0')
     154  	    {
     155  	      printf ("conversion with %s failed\n", modules[idx].name);
     156  	      result = 1;
     157  	    }
     158  	}
     159        else
     160  	{
     161  	  /* Unload the module.  */
     162  	  if (iconv_close (modules[idx].cd) != 0)
     163  	    {
     164  	      printf ("closing of %s failed: %m\n", modules[idx].name);
     165  	      result = 1;
     166  	      break;
     167  	    }
     168  
     169  	  modules[idx].state = unloaded;
     170  	}
     171      }
     172  
     173    for (count = 0; count < nmodules; ++count)
     174      if (modules[count].state == loaded && iconv_close (modules[count].cd) != 0)
     175        {
     176  	printf ("closing of %s failed: %m\n", modules[count].name);
     177  	result = 1;
     178        }
     179  
     180    return result;
     181  }
     182  
     183  #define TIMEOUT 30
     184  #define TEST_FUNCTION do_test ()
     185  #include "../test-skeleton.c"