Blame gettext-tools/gnulib-lib/striconv.c

Packit Bot 06c835
/* Charset conversion.
Packit Bot 06c835
   Copyright (C) 2001-2007, 2010-2015 Free Software Foundation, Inc.
Packit Bot 06c835
   Written by Bruno Haible and Simon Josefsson.
Packit Bot 06c835
Packit Bot 06c835
   This program is free software; you can redistribute it and/or modify
Packit Bot 06c835
   it under the terms of the GNU General Public License as published by
Packit Bot 06c835
   the Free Software Foundation; either version 3, or (at your option)
Packit Bot 06c835
   any later version.
Packit Bot 06c835
Packit Bot 06c835
   This program is distributed in the hope that it will be useful,
Packit Bot 06c835
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Bot 06c835
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Bot 06c835
   GNU General Public License for more details.
Packit Bot 06c835
Packit Bot 06c835
   You should have received a copy of the GNU General Public License
Packit Bot 06c835
   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
Packit Bot 06c835
Packit Bot 06c835
#include <config.h>
Packit Bot 06c835
Packit Bot 06c835
/* Specification.  */
Packit Bot 06c835
#include "striconv.h"
Packit Bot 06c835
Packit Bot 06c835
#include <errno.h>
Packit Bot 06c835
#include <stdlib.h>
Packit Bot 06c835
#include <string.h>
Packit Bot 06c835
Packit Bot 06c835
#if HAVE_ICONV
Packit Bot 06c835
# include <iconv.h>
Packit Bot 06c835
/* Get MB_LEN_MAX, CHAR_BIT.  */
Packit Bot 06c835
# include <limits.h>
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
#include "c-strcase.h"
Packit Bot 06c835
Packit Bot 06c835
#ifndef SIZE_MAX
Packit Bot 06c835
# define SIZE_MAX ((size_t) -1)
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
Packit Bot 06c835
#if HAVE_ICONV
Packit Bot 06c835
Packit Bot 06c835
int
Packit Bot 06c835
mem_cd_iconv (const char *src, size_t srclen, iconv_t cd,
Packit Bot 06c835
              char **resultp, size_t *lengthp)
Packit Bot 06c835
{
Packit Bot 06c835
# define tmpbufsize 4096
Packit Bot 06c835
  size_t length;
Packit Bot 06c835
  char *result;
Packit Bot 06c835
Packit Bot 06c835
  /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug.  */
Packit Bot 06c835
# if defined _LIBICONV_VERSION \
Packit Bot 06c835
     || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
          || defined __sun)
Packit Bot 06c835
  /* Set to the initial state.  */
Packit Bot 06c835
  iconv (cd, NULL, NULL, NULL, NULL);
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
  /* Determine the length we need.  */
Packit Bot 06c835
  {
Packit Bot 06c835
    size_t count = 0;
Packit Bot 06c835
    /* The alignment is needed when converting e.g. to glibc's WCHAR_T or
Packit Bot 06c835
       libiconv's UCS-4-INTERNAL encoding.  */
Packit Bot 06c835
    union { unsigned int align; char buf[tmpbufsize]; } tmp;
Packit Bot 06c835
# define tmpbuf tmp.buf
Packit Bot 06c835
    const char *inptr = src;
Packit Bot 06c835
    size_t insize = srclen;
Packit Bot 06c835
Packit Bot 06c835
    while (insize > 0)
Packit Bot 06c835
      {
Packit Bot 06c835
        char *outptr = tmpbuf;
Packit Bot 06c835
        size_t outsize = tmpbufsize;
Packit Bot 06c835
        size_t res = iconv (cd,
Packit Bot 06c835
                            (ICONV_CONST char **) &inptr, &insize,
Packit Bot 06c835
                            &outptr, &outsize);
Packit Bot 06c835
Packit Bot 06c835
        if (res == (size_t)(-1))
Packit Bot 06c835
          {
Packit Bot 06c835
            if (errno == E2BIG)
Packit Bot 06c835
              ;
Packit Bot 06c835
            else if (errno == EINVAL)
Packit Bot 06c835
              break;
Packit Bot 06c835
            else
Packit Bot 06c835
              return -1;
Packit Bot 06c835
          }
Packit Bot 06c835
# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)
Packit Bot 06c835
        /* Irix iconv() inserts a NUL byte if it cannot convert.
Packit Bot 06c835
           NetBSD iconv() inserts a question mark if it cannot convert.
Packit Bot 06c835
           Only GNU libiconv and GNU libc are known to prefer to fail rather
Packit Bot 06c835
           than doing a lossy conversion.  */
Packit Bot 06c835
        else if (res > 0)
Packit Bot 06c835
          {
Packit Bot 06c835
            errno = EILSEQ;
Packit Bot 06c835
            return -1;
Packit Bot 06c835
          }
Packit Bot 06c835
# endif
Packit Bot 06c835
        count += outptr - tmpbuf;
Packit Bot 06c835
      }
Packit Bot 06c835
    /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
Packit Bot 06c835
# if defined _LIBICONV_VERSION \
Packit Bot 06c835
     || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
          || defined __sun)
Packit Bot 06c835
    {
Packit Bot 06c835
      char *outptr = tmpbuf;
Packit Bot 06c835
      size_t outsize = tmpbufsize;
Packit Bot 06c835
      size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);
Packit Bot 06c835
Packit Bot 06c835
      if (res == (size_t)(-1))
Packit Bot 06c835
        return -1;
Packit Bot 06c835
      count += outptr - tmpbuf;
Packit Bot 06c835
    }
Packit Bot 06c835
# endif
Packit Bot 06c835
    length = count;
Packit Bot 06c835
# undef tmpbuf
Packit Bot 06c835
  }
Packit Bot 06c835
Packit Bot 06c835
  if (length == 0)
Packit Bot 06c835
    {
Packit Bot 06c835
      *lengthp = 0;
Packit Bot 06c835
      return 0;
Packit Bot 06c835
    }
Packit Bot 06c835
  if (*resultp != NULL && *lengthp >= length)
Packit Bot 06c835
    result = *resultp;
Packit Bot 06c835
  else
Packit Bot 06c835
    {
Packit Bot 06c835
      result = (char *) malloc (length);
Packit Bot 06c835
      if (result == NULL)
Packit Bot 06c835
        {
Packit Bot 06c835
          errno = ENOMEM;
Packit Bot 06c835
          return -1;
Packit Bot 06c835
        }
Packit Bot 06c835
    }
Packit Bot 06c835
Packit Bot 06c835
  /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug.  */
Packit Bot 06c835
# if defined _LIBICONV_VERSION \
Packit Bot 06c835
     || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
          || defined __sun)
Packit Bot 06c835
  /* Return to the initial state.  */
Packit Bot 06c835
  iconv (cd, NULL, NULL, NULL, NULL);
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
  /* Do the conversion for real.  */
Packit Bot 06c835
  {
Packit Bot 06c835
    const char *inptr = src;
Packit Bot 06c835
    size_t insize = srclen;
Packit Bot 06c835
    char *outptr = result;
Packit Bot 06c835
    size_t outsize = length;
Packit Bot 06c835
Packit Bot 06c835
    while (insize > 0)
Packit Bot 06c835
      {
Packit Bot 06c835
        size_t res = iconv (cd,
Packit Bot 06c835
                            (ICONV_CONST char **) &inptr, &insize,
Packit Bot 06c835
                            &outptr, &outsize);
Packit Bot 06c835
Packit Bot 06c835
        if (res == (size_t)(-1))
Packit Bot 06c835
          {
Packit Bot 06c835
            if (errno == EINVAL)
Packit Bot 06c835
              break;
Packit Bot 06c835
            else
Packit Bot 06c835
              goto fail;
Packit Bot 06c835
          }
Packit Bot 06c835
# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)
Packit Bot 06c835
        /* Irix iconv() inserts a NUL byte if it cannot convert.
Packit Bot 06c835
           NetBSD iconv() inserts a question mark if it cannot convert.
Packit Bot 06c835
           Only GNU libiconv and GNU libc are known to prefer to fail rather
Packit Bot 06c835
           than doing a lossy conversion.  */
Packit Bot 06c835
        else if (res > 0)
Packit Bot 06c835
          {
Packit Bot 06c835
            errno = EILSEQ;
Packit Bot 06c835
            goto fail;
Packit Bot 06c835
          }
Packit Bot 06c835
# endif
Packit Bot 06c835
      }
Packit Bot 06c835
    /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
Packit Bot 06c835
# if defined _LIBICONV_VERSION \
Packit Bot 06c835
     || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
          || defined __sun)
Packit Bot 06c835
    {
Packit Bot 06c835
      size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);
Packit Bot 06c835
Packit Bot 06c835
      if (res == (size_t)(-1))
Packit Bot 06c835
        goto fail;
Packit Bot 06c835
    }
Packit Bot 06c835
# endif
Packit Bot 06c835
    if (outsize != 0)
Packit Bot 06c835
      abort ();
Packit Bot 06c835
  }
Packit Bot 06c835
Packit Bot 06c835
  *resultp = result;
Packit Bot 06c835
  *lengthp = length;
Packit Bot 06c835
Packit Bot 06c835
  return 0;
Packit Bot 06c835
Packit Bot 06c835
 fail:
Packit Bot 06c835
  {
Packit Bot 06c835
    if (result != *resultp)
Packit Bot 06c835
      {
Packit Bot 06c835
        int saved_errno = errno;
Packit Bot 06c835
        free (result);
Packit Bot 06c835
        errno = saved_errno;
Packit Bot 06c835
      }
Packit Bot 06c835
    return -1;
Packit Bot 06c835
  }
Packit Bot 06c835
# undef tmpbufsize
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
char *
Packit Bot 06c835
str_cd_iconv (const char *src, iconv_t cd)
Packit Bot 06c835
{
Packit Bot 06c835
  /* For most encodings, a trailing NUL byte in the input will be converted
Packit Bot 06c835
     to a trailing NUL byte in the output.  But not for UTF-7.  So that this
Packit Bot 06c835
     function is usable for UTF-7, we have to exclude the NUL byte from the
Packit Bot 06c835
     conversion and add it by hand afterwards.  */
Packit Bot 06c835
# if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)
Packit Bot 06c835
  /* Irix iconv() inserts a NUL byte if it cannot convert.
Packit Bot 06c835
     NetBSD iconv() inserts a question mark if it cannot convert.
Packit Bot 06c835
     Only GNU libiconv and GNU libc are known to prefer to fail rather
Packit Bot 06c835
     than doing a lossy conversion.  For other iconv() implementations,
Packit Bot 06c835
     we have to look at the number of irreversible conversions returned;
Packit Bot 06c835
     but this information is lost when iconv() returns for an E2BIG reason.
Packit Bot 06c835
     Therefore we cannot use the second, faster algorithm.  */
Packit Bot 06c835
Packit Bot 06c835
  char *result = NULL;
Packit Bot 06c835
  size_t length = 0;
Packit Bot 06c835
  int retval = mem_cd_iconv (src, strlen (src), cd, &result, &length);
Packit Bot 06c835
  char *final_result;
Packit Bot 06c835
Packit Bot 06c835
  if (retval < 0)
Packit Bot 06c835
    {
Packit Bot 06c835
      if (result != NULL)
Packit Bot 06c835
        abort ();
Packit Bot 06c835
      return NULL;
Packit Bot 06c835
    }
Packit Bot 06c835
Packit Bot 06c835
  /* Add the terminating NUL byte.  */
Packit Bot 06c835
  final_result =
Packit Bot 06c835
    (result != NULL ? realloc (result, length + 1) : malloc (length + 1));
Packit Bot 06c835
  if (final_result == NULL)
Packit Bot 06c835
    {
Packit Bot 06c835
      free (result);
Packit Bot 06c835
      errno = ENOMEM;
Packit Bot 06c835
      return NULL;
Packit Bot 06c835
    }
Packit Bot 06c835
  final_result[length] = '\0';
Packit Bot 06c835
Packit Bot 06c835
  return final_result;
Packit Bot 06c835
Packit Bot 06c835
# else
Packit Bot 06c835
  /* This algorithm is likely faster than the one above.  But it may produce
Packit Bot 06c835
     iconv() returns for an E2BIG reason, when the output size guess is too
Packit Bot 06c835
     small.  Therefore it can only be used when we don't need the number of
Packit Bot 06c835
     irreversible conversions performed.  */
Packit Bot 06c835
  char *result;
Packit Bot 06c835
  size_t result_size;
Packit Bot 06c835
  size_t length;
Packit Bot 06c835
  const char *inptr = src;
Packit Bot 06c835
  size_t inbytes_remaining = strlen (src);
Packit Bot 06c835
Packit Bot 06c835
  /* Make a guess for the worst-case output size, in order to avoid a
Packit Bot 06c835
     realloc.  It's OK if the guess is wrong as long as it is not zero and
Packit Bot 06c835
     doesn't lead to an integer overflow.  */
Packit Bot 06c835
  result_size = inbytes_remaining;
Packit Bot 06c835
  {
Packit Bot 06c835
    size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2);
Packit Bot 06c835
    if (result_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX)
Packit Bot 06c835
      result_size *= MB_LEN_MAX;
Packit Bot 06c835
  }
Packit Bot 06c835
  result_size += 1; /* for the terminating NUL */
Packit Bot 06c835
Packit Bot 06c835
  result = (char *) malloc (result_size);
Packit Bot 06c835
  if (result == NULL)
Packit Bot 06c835
    {
Packit Bot 06c835
      errno = ENOMEM;
Packit Bot 06c835
      return NULL;
Packit Bot 06c835
    }
Packit Bot 06c835
Packit Bot 06c835
  /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug.  */
Packit Bot 06c835
# if defined _LIBICONV_VERSION \
Packit Bot 06c835
     || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
          || defined __sun)
Packit Bot 06c835
  /* Set to the initial state.  */
Packit Bot 06c835
  iconv (cd, NULL, NULL, NULL, NULL);
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
  /* Do the conversion.  */
Packit Bot 06c835
  {
Packit Bot 06c835
    char *outptr = result;
Packit Bot 06c835
    size_t outbytes_remaining = result_size - 1;
Packit Bot 06c835
Packit Bot 06c835
    for (;;)
Packit Bot 06c835
      {
Packit Bot 06c835
        /* Here inptr + inbytes_remaining = src + strlen (src),
Packit Bot 06c835
                outptr + outbytes_remaining = result + result_size - 1.  */
Packit Bot 06c835
        size_t res = iconv (cd,
Packit Bot 06c835
                            (ICONV_CONST char **) &inptr, &inbytes_remaining,
Packit Bot 06c835
                            &outptr, &outbytes_remaining);
Packit Bot 06c835
Packit Bot 06c835
        if (res == (size_t)(-1))
Packit Bot 06c835
          {
Packit Bot 06c835
            if (errno == EINVAL)
Packit Bot 06c835
              break;
Packit Bot 06c835
            else if (errno == E2BIG)
Packit Bot 06c835
              {
Packit Bot 06c835
                size_t used = outptr - result;
Packit Bot 06c835
                size_t newsize = result_size * 2;
Packit Bot 06c835
                char *newresult;
Packit Bot 06c835
Packit Bot 06c835
                if (!(newsize > result_size))
Packit Bot 06c835
                  {
Packit Bot 06c835
                    errno = ENOMEM;
Packit Bot 06c835
                    goto failed;
Packit Bot 06c835
                  }
Packit Bot 06c835
                newresult = (char *) realloc (result, newsize);
Packit Bot 06c835
                if (newresult == NULL)
Packit Bot 06c835
                  {
Packit Bot 06c835
                    errno = ENOMEM;
Packit Bot 06c835
                    goto failed;
Packit Bot 06c835
                  }
Packit Bot 06c835
                result = newresult;
Packit Bot 06c835
                result_size = newsize;
Packit Bot 06c835
                outptr = result + used;
Packit Bot 06c835
                outbytes_remaining = result_size - 1 - used;
Packit Bot 06c835
              }
Packit Bot 06c835
            else
Packit Bot 06c835
              goto failed;
Packit Bot 06c835
          }
Packit Bot 06c835
        else
Packit Bot 06c835
          break;
Packit Bot 06c835
      }
Packit Bot 06c835
    /* Avoid glibc-2.1 bug and Solaris 2.7 bug.  */
Packit Bot 06c835
# if defined _LIBICONV_VERSION \
Packit Bot 06c835
     || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
          || defined __sun)
Packit Bot 06c835
    for (;;)
Packit Bot 06c835
      {
Packit Bot 06c835
        /* Here outptr + outbytes_remaining = result + result_size - 1.  */
Packit Bot 06c835
        size_t res = iconv (cd, NULL, NULL, &outptr, &outbytes_remaining);
Packit Bot 06c835
Packit Bot 06c835
        if (res == (size_t)(-1))
Packit Bot 06c835
          {
Packit Bot 06c835
            if (errno == E2BIG)
Packit Bot 06c835
              {
Packit Bot 06c835
                size_t used = outptr - result;
Packit Bot 06c835
                size_t newsize = result_size * 2;
Packit Bot 06c835
                char *newresult;
Packit Bot 06c835
Packit Bot 06c835
                if (!(newsize > result_size))
Packit Bot 06c835
                  {
Packit Bot 06c835
                    errno = ENOMEM;
Packit Bot 06c835
                    goto failed;
Packit Bot 06c835
                  }
Packit Bot 06c835
                newresult = (char *) realloc (result, newsize);
Packit Bot 06c835
                if (newresult == NULL)
Packit Bot 06c835
                  {
Packit Bot 06c835
                    errno = ENOMEM;
Packit Bot 06c835
                    goto failed;
Packit Bot 06c835
                  }
Packit Bot 06c835
                result = newresult;
Packit Bot 06c835
                result_size = newsize;
Packit Bot 06c835
                outptr = result + used;
Packit Bot 06c835
                outbytes_remaining = result_size - 1 - used;
Packit Bot 06c835
              }
Packit Bot 06c835
            else
Packit Bot 06c835
              goto failed;
Packit Bot 06c835
          }
Packit Bot 06c835
        else
Packit Bot 06c835
          break;
Packit Bot 06c835
      }
Packit Bot 06c835
# endif
Packit Bot 06c835
Packit Bot 06c835
    /* Add the terminating NUL byte.  */
Packit Bot 06c835
    *outptr++ = '\0';
Packit Bot 06c835
Packit Bot 06c835
    length = outptr - result;
Packit Bot 06c835
  }
Packit Bot 06c835
Packit Bot 06c835
  /* Give away unused memory.  */
Packit Bot 06c835
  if (length < result_size)
Packit Bot 06c835
    {
Packit Bot 06c835
      char *smaller_result = (char *) realloc (result, length);
Packit Bot 06c835
Packit Bot 06c835
      if (smaller_result != NULL)
Packit Bot 06c835
        result = smaller_result;
Packit Bot 06c835
    }
Packit Bot 06c835
Packit Bot 06c835
  return result;
Packit Bot 06c835
Packit Bot 06c835
 failed:
Packit Bot 06c835
  {
Packit Bot 06c835
    int saved_errno = errno;
Packit Bot 06c835
    free (result);
Packit Bot 06c835
    errno = saved_errno;
Packit Bot 06c835
    return NULL;
Packit Bot 06c835
  }
Packit Bot 06c835
Packit Bot 06c835
# endif
Packit Bot 06c835
}
Packit Bot 06c835
Packit Bot 06c835
#endif
Packit Bot 06c835
Packit Bot 06c835
char *
Packit Bot 06c835
str_iconv (const char *src, const char *from_codeset, const char *to_codeset)
Packit Bot 06c835
{
Packit Bot 06c835
  if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
Packit Bot 06c835
    {
Packit Bot 06c835
      char *result = strdup (src);
Packit Bot 06c835
Packit Bot 06c835
      if (result == NULL)
Packit Bot 06c835
        errno = ENOMEM;
Packit Bot 06c835
      return result;
Packit Bot 06c835
    }
Packit Bot 06c835
  else
Packit Bot 06c835
    {
Packit Bot 06c835
#if HAVE_ICONV
Packit Bot 06c835
      iconv_t cd;
Packit Bot 06c835
      char *result;
Packit Bot 06c835
Packit Bot 06c835
      /* Avoid glibc-2.1 bug with EUC-KR.  */
Packit Bot 06c835
# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
Packit Bot 06c835
     && !defined _LIBICONV_VERSION
Packit Bot 06c835
      if (c_strcasecmp (from_codeset, "EUC-KR") == 0
Packit Bot 06c835
          || c_strcasecmp (to_codeset, "EUC-KR") == 0)
Packit Bot 06c835
        {
Packit Bot 06c835
          errno = EINVAL;
Packit Bot 06c835
          return NULL;
Packit Bot 06c835
        }
Packit Bot 06c835
# endif
Packit Bot 06c835
      cd = iconv_open (to_codeset, from_codeset);
Packit Bot 06c835
      if (cd == (iconv_t) -1)
Packit Bot 06c835
        return NULL;
Packit Bot 06c835
Packit Bot 06c835
      result = str_cd_iconv (src, cd);
Packit Bot 06c835
Packit Bot 06c835
      if (result == NULL)
Packit Bot 06c835
        {
Packit Bot 06c835
          /* Close cd, but preserve the errno from str_cd_iconv.  */
Packit Bot 06c835
          int saved_errno = errno;
Packit Bot 06c835
          iconv_close (cd);
Packit Bot 06c835
          errno = saved_errno;
Packit Bot 06c835
        }
Packit Bot 06c835
      else
Packit Bot 06c835
        {
Packit Bot 06c835
          if (iconv_close (cd) < 0)
Packit Bot 06c835
            {
Packit Bot 06c835
              /* Return NULL, but free the allocated memory, and while doing
Packit Bot 06c835
                 that, preserve the errno from iconv_close.  */
Packit Bot 06c835
              int saved_errno = errno;
Packit Bot 06c835
              free (result);
Packit Bot 06c835
              errno = saved_errno;
Packit Bot 06c835
              return NULL;
Packit Bot 06c835
            }
Packit Bot 06c835
        }
Packit Bot 06c835
      return result;
Packit Bot 06c835
#else
Packit Bot 06c835
      /* This is a different error code than if iconv_open existed but didn't
Packit Bot 06c835
         support from_codeset and to_codeset, so that the caller can emit
Packit Bot 06c835
         an error message such as
Packit Bot 06c835
           "iconv() is not supported. Installing GNU libiconv and
Packit Bot 06c835
            then reinstalling this package would fix this."  */
Packit Bot 06c835
      errno = ENOSYS;
Packit Bot 06c835
      return NULL;
Packit Bot 06c835
#endif
Packit Bot 06c835
    }
Packit Bot 06c835
}