strerror_r.c 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* $OpenBSD: strerror_r.c,v 1.8 2013/06/01 21:26:18 stsp Exp $ */
  2. /* Public Domain <marc@snafu.org> */
  3. #include <errno.h>
  4. #include <limits.h>
  5. #include <string.h>
  6. extern int sys_nerr;
  7. extern const char *const sys_errlist[];
  8. static size_t
  9. __digits10(unsigned int num)
  10. {
  11. size_t i = 0;
  12. do {
  13. num /= 10;
  14. i++;
  15. } while (num != 0);
  16. return i;
  17. }
  18. static int
  19. __itoa(int num, int sign, char *buffer, size_t start, size_t end)
  20. {
  21. size_t pos;
  22. unsigned int a;
  23. int neg;
  24. if (sign && num < 0) {
  25. a = -num;
  26. neg = 1;
  27. }
  28. else {
  29. a = num;
  30. neg = 0;
  31. }
  32. pos = start + __digits10(a);
  33. if (neg)
  34. pos++;
  35. if (pos < end)
  36. buffer[pos] = '\0';
  37. else
  38. return ERANGE;
  39. pos--;
  40. do {
  41. buffer[pos] = (a % 10) + '0';
  42. pos--;
  43. a /= 10;
  44. } while (a != 0);
  45. if (neg)
  46. buffer[pos] = '-';
  47. return 0;
  48. }
  49. static int
  50. __num2string(int num, int sign, int setid, char *buf, size_t buflen,
  51. const char *const list[], size_t max, const char *def)
  52. {
  53. int ret = 0;
  54. size_t len;
  55. (void *)&setid;
  56. if (0 <= num && num < max) {
  57. len = strlcpy(buf, list[num], buflen);
  58. if (len >= buflen)
  59. ret = ERANGE;
  60. } else {
  61. len = strlcpy(buf, def, buflen);
  62. if (len >= buflen)
  63. ret = ERANGE;
  64. else {
  65. ret = __itoa(num, sign, buf, len, buflen);
  66. if (ret == 0)
  67. ret = EINVAL;
  68. }
  69. }
  70. return ret;
  71. }
  72. #define UPREFIX "Unknown error: "
  73. int
  74. strerror_r(int errnum, char *strerrbuf, size_t buflen)
  75. {
  76. int save_errno;
  77. int ret_errno;
  78. save_errno = errno;
  79. ret_errno = __num2string(errnum, 1, 1, strerrbuf, buflen,
  80. sys_errlist, sys_nerr, UPREFIX);
  81. errno = ret_errno ? ret_errno : save_errno;
  82. return (ret_errno);
  83. }