strerror_l.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. /* Copyright (C) 2007-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Lesser General Public
  5. License as published by the Free Software Foundation; either
  6. version 2.1 of the License, or (at your option) any later version.
  7. The GNU C Library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Lesser General Public License for more details.
  11. You should have received a copy of the GNU Lesser General Public
  12. License along with the GNU C Library; if not, see
  13. <https://www.gnu.org/licenses/>. */
  14. #include <libintl.h>
  15. #include <locale.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <tls-internal.h>
  19. #include <libc-internal.h>
  20. static const char *
  21. translate (const char *str, locale_t loc)
  22. {
  23. locale_t oldloc = __uselocale (loc);
  24. const char *res = _(str);
  25. __uselocale (oldloc);
  26. return res;
  27. }
  28. static char *
  29. unknown_error (locale_t loc)
  30. {
  31. return (char *) translate ("Unknown error", loc);
  32. }
  33. /* Return a string describing the errno code in ERRNUM. */
  34. char *
  35. __strerror_l (int errnum, locale_t loc)
  36. {
  37. int saved_errno = errno;
  38. char *err = (char *) __get_errlist (errnum);
  39. if (__glibc_unlikely (err == NULL))
  40. {
  41. if (__libc_initial)
  42. {
  43. struct tls_internal_t *tls_internal = __glibc_tls_internal ();
  44. free (tls_internal->strerror_l_buf);
  45. if (__asprintf (&tls_internal->strerror_l_buf, "%s%d",
  46. translate ("Unknown error ", loc), errnum) > 0)
  47. err = tls_internal->strerror_l_buf;
  48. else
  49. {
  50. /* The memory was freed above. */
  51. tls_internal->strerror_l_buf = NULL;
  52. /* Provide a fallback translation. */
  53. err = unknown_error (loc);
  54. }
  55. }
  56. else
  57. /* Secondary namespaces use a different malloc, so cannot
  58. participate in the buffer management. */
  59. err = unknown_error (loc);
  60. }
  61. else
  62. err = (char *) translate (err, loc);
  63. __set_errno (saved_errno);
  64. return err;
  65. }
  66. weak_alias (__strerror_l, strerror_l)
  67. libc_hidden_def (__strerror_l)