1 /* strerror_l - Get errno description string in given locale.  Mach version.
2    Copyright (C) 2007-2022 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 *
translate(const char * str,locale_t loc)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 *
__strerror_l(int errnum,locale_t loc)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) == -1)
65 	tls_internal->strerror_l_buf = NULL;
66 
67       __set_errno (saved_errno);
68       return tls_internal->strerror_l_buf;
69     }
70 
71   es = &__mach_error_systems[system];
72 
73   if (sub >= es->max_sub)
74     err = (char *) translate (es->bad_sub, loc);
75   else if (code >= es->subsystem[sub].max_code)
76     {
77       struct tls_internal_t *tls_internal = __glibc_tls_internal ();
78       free (tls_internal->strerror_l_buf);
79       if (__asprintf (&tls_internal->strerror_l_buf, "%s%s %d",
80 		      translate ("Unknown error ", loc),
81 		      translate (es->subsystem[sub].subsys_name, loc),
82 		      errnum) == -1)
83 	tls_internal->strerror_l_buf = NULL;
84 
85       err = tls_internal->strerror_l_buf;
86     }
87   else
88     err = (char *) translate (es->subsystem[sub].codes[code], loc);
89 
90   __set_errno (saved_errno);
91   return err;
92 }
93 weak_alias (__strerror_l, strerror_l)
94 libc_hidden_def (__strerror_l)
95