1  /* strerror_l - Get errno description string in given locale.  Mach version.
       2     Copyright (C) 2007-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 <libintl.h>
      20  #include <locale.h>
      21  #include <stdio.h>
      22  #include <stdlib.h>
      23  #include <string.h>
      24  #include <errno.h>
      25  #include <mach/error.h>
      26  #include <errorlib.h>
      27  #include <tls-internal.h>
      28  
      29  
      30  static const char *
      31  translate (const char *str, locale_t loc)
      32  {
      33    locale_t oldloc = __uselocale (loc);
      34    const char *res = _(str);
      35    __uselocale (oldloc);
      36    return res;
      37  }
      38  
      39  
      40  /* Return a string describing the errno code in ERRNUM.  */
      41  char *
      42  __strerror_l (int errnum, locale_t loc)
      43  {
      44    int saved_errno = errno;
      45    char *err;
      46    int system;
      47    int sub;
      48    int code;
      49    const struct error_system *es;
      50    extern void __mach_error_map_compat (int *);
      51  
      52    __mach_error_map_compat (&errnum);
      53  
      54    system = err_get_system (errnum);
      55    sub = err_get_sub (errnum);
      56    code = err_get_code (errnum);
      57  
      58    if (system > err_max_system || ! __mach_error_systems[system].bad_sub)
      59      {
      60        struct tls_internal_t *tls_internal = __glibc_tls_internal ();
      61        free (tls_internal->strerror_l_buf);
      62        if (__asprintf (&tls_internal->strerror_l_buf, "%s%X",
      63  		      translate ("Error in unknown error system: ", loc),
      64  		      errnum) > 0)
      65  	err = tls_internal->strerror_l_buf;
      66        else
      67  	{
      68  	  /* The memory was freed above.  */
      69  	  tls_internal->strerror_l_buf = NULL;
      70  	  /* Provide a fallback translation.  */
      71  	  err = (char *) translate ("Unknown error", loc);
      72  	}
      73  
      74        __set_errno (saved_errno);
      75        return err;
      76      }
      77  
      78    es = &__mach_error_systems[system];
      79  
      80    if (sub >= es->max_sub)
      81      err = (char *) translate (es->bad_sub, loc);
      82    else if (code >= es->subsystem[sub].max_code)
      83      {
      84        struct tls_internal_t *tls_internal = __glibc_tls_internal ();
      85        free (tls_internal->strerror_l_buf);
      86        if (__asprintf (&tls_internal->strerror_l_buf, "%s%s %d",
      87  		      translate ("Unknown error ", loc),
      88  		      translate (es->subsystem[sub].subsys_name, loc),
      89  		      errnum) > 0)
      90  	err = tls_internal->strerror_l_buf;
      91        else
      92  	{
      93  	  /* The memory was freed above.  */
      94  	  tls_internal->strerror_l_buf = NULL;
      95  	  /* Provide a fallback translation.  */
      96  	  err = (char *) translate ("Unknown error", loc);
      97  	}
      98      }
      99    else
     100      err = (char *) translate (es->subsystem[sub].codes[code], loc);
     101  
     102    __set_errno (saved_errno);
     103    return err;
     104  }
     105  weak_alias (__strerror_l, strerror_l)
     106  libc_hidden_def (__strerror_l)