__xpg_strerror_r.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. /*
  2. * Copyright (C) 2002 Manuel Novoa III
  3. * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
  4. *
  5. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  6. */
  7. #define _GNU_SOURCE
  8. #include <features.h>
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <bits/uClibc_uintmaxtostr.h>
  12. #include "_syserrmsg.h"
  13. libc_hidden_proto(__xpg_strerror_r)
  14. libc_hidden_proto(memcpy)
  15. libc_hidden_proto(strlen)
  16. #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
  17. extern const char _string_syserrmsgs[] attribute_hidden;
  18. #if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
  19. static const unsigned char estridx[] = {
  20. 0, /* success is always 0 */
  21. EPERM,
  22. ENOENT,
  23. ESRCH,
  24. EINTR,
  25. EIO,
  26. ENXIO,
  27. E2BIG,
  28. ENOEXEC,
  29. EBADF,
  30. ECHILD,
  31. EAGAIN,
  32. ENOMEM,
  33. EACCES,
  34. EFAULT,
  35. ENOTBLK,
  36. EBUSY,
  37. EEXIST,
  38. EXDEV,
  39. ENODEV,
  40. ENOTDIR,
  41. EISDIR,
  42. EINVAL,
  43. ENFILE,
  44. EMFILE,
  45. ENOTTY,
  46. ETXTBSY,
  47. EFBIG,
  48. ENOSPC,
  49. ESPIPE,
  50. EROFS,
  51. EMLINK,
  52. EPIPE,
  53. EDOM,
  54. ERANGE,
  55. EDEADLK,
  56. ENAMETOOLONG,
  57. ENOLCK,
  58. ENOSYS,
  59. ENOTEMPTY,
  60. ELOOP,
  61. 0,
  62. ENOMSG,
  63. EIDRM,
  64. ECHRNG,
  65. EL2NSYNC,
  66. EL3HLT,
  67. EL3RST,
  68. ELNRNG,
  69. EUNATCH,
  70. ENOCSI,
  71. EL2HLT,
  72. EBADE,
  73. EBADR,
  74. EXFULL,
  75. ENOANO,
  76. EBADRQC,
  77. EBADSLT,
  78. 0,
  79. EBFONT,
  80. ENOSTR,
  81. ENODATA,
  82. ETIME,
  83. ENOSR,
  84. ENONET,
  85. ENOPKG,
  86. EREMOTE,
  87. ENOLINK,
  88. EADV,
  89. ESRMNT,
  90. ECOMM,
  91. EPROTO,
  92. EMULTIHOP,
  93. EDOTDOT,
  94. EBADMSG,
  95. EOVERFLOW,
  96. ENOTUNIQ,
  97. EBADFD,
  98. EREMCHG,
  99. ELIBACC,
  100. ELIBBAD,
  101. ELIBSCN,
  102. ELIBMAX,
  103. ELIBEXEC,
  104. EILSEQ,
  105. ERESTART,
  106. ESTRPIPE,
  107. EUSERS,
  108. ENOTSOCK,
  109. EDESTADDRREQ,
  110. EMSGSIZE,
  111. EPROTOTYPE,
  112. ENOPROTOOPT,
  113. EPROTONOSUPPORT,
  114. ESOCKTNOSUPPORT,
  115. EOPNOTSUPP,
  116. EPFNOSUPPORT,
  117. EAFNOSUPPORT,
  118. EADDRINUSE,
  119. EADDRNOTAVAIL,
  120. ENETDOWN,
  121. ENETUNREACH,
  122. ENETRESET,
  123. ECONNABORTED,
  124. ECONNRESET,
  125. ENOBUFS,
  126. EISCONN,
  127. ENOTCONN,
  128. ESHUTDOWN,
  129. ETOOMANYREFS,
  130. ETIMEDOUT,
  131. ECONNREFUSED,
  132. EHOSTDOWN,
  133. EHOSTUNREACH,
  134. EALREADY,
  135. EINPROGRESS,
  136. ESTALE,
  137. EUCLEAN,
  138. ENOTNAM,
  139. ENAVAIL,
  140. EISNAM,
  141. EREMOTEIO,
  142. #ifdef __mips__
  143. 0, /* mips has an outrageous value for this... */
  144. #else
  145. EDQUOT,
  146. #endif
  147. ENOMEDIUM,
  148. EMEDIUMTYPE,
  149. #if defined(__mips__) || defined(__sparc__)
  150. EDEADLOCK,
  151. #endif
  152. };
  153. #endif
  154. int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
  155. {
  156. register char *s;
  157. int i, retval;
  158. char buf[_STRERROR_BUFSIZE];
  159. static const char unknown[] = {
  160. 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
  161. };
  162. retval = EINVAL;
  163. #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
  164. #if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
  165. /* Need to translate errno to string index. */
  166. for (i = 0 ; i < sizeof(estridx)/sizeof(estridx[0]) ; i++) {
  167. if (estridx[i] == errnum) {
  168. goto GOT_ESTRIDX;
  169. }
  170. }
  171. i = INT_MAX; /* Failed, but may need to check mips special case. */
  172. #ifdef __mips__
  173. if (errnum == EDQUOT) { /* Deal with large EDQUOT value on mips */
  174. i = 122;
  175. }
  176. #endif /* __mips__ */
  177. GOT_ESTRIDX:
  178. #else
  179. /* No errno to string index translation needed. */
  180. i = errnum;
  181. #endif
  182. if (((unsigned int) i) < _SYS_NERR) {
  183. /* Trade time for space. This function should rarely be called
  184. * so rather than keeping an array of pointers for the different
  185. * messages, just run through the buffer until we find the
  186. * correct string. */
  187. for (s = (char *) _string_syserrmsgs ; i ; ++s) {
  188. if (!*s) {
  189. --i;
  190. }
  191. }
  192. if (*s) { /* Make sure we have an actual message. */
  193. retval = 0;
  194. goto GOT_MESG;
  195. }
  196. }
  197. #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
  198. s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
  199. memcpy(s, unknown, sizeof(unknown));
  200. GOT_MESG:
  201. if (!strerrbuf) { /* SUSv3 */
  202. buflen = 0;
  203. }
  204. i = strlen(s) + 1;
  205. if (i > buflen) {
  206. i = buflen;
  207. retval = ERANGE;
  208. }
  209. if (i) {
  210. memcpy(strerrbuf, s, i);
  211. strerrbuf[i-1] = 0; /* In case buf was too small. */
  212. }
  213. if (retval) {
  214. __set_errno(retval);
  215. }
  216. return retval;
  217. }
  218. #else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
  219. int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
  220. {
  221. register char *s;
  222. int i, retval;
  223. char buf[_STRERROR_BUFSIZE];
  224. static const char unknown[] = {
  225. 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
  226. };
  227. s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
  228. memcpy(s, unknown, sizeof(unknown));
  229. if (!strerrbuf) { /* SUSv3 */
  230. buflen = 0;
  231. }
  232. retval = EINVAL;
  233. i = buf + sizeof(buf) - s;
  234. if (i > buflen) {
  235. i = buflen;
  236. retval = ERANGE;
  237. }
  238. if (i) {
  239. memcpy(strerrbuf, s, i);
  240. strerrbuf[i-1] = 0; /* In case buf was too small. */
  241. }
  242. __set_errno(retval);
  243. return retval;
  244. }
  245. #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
  246. libc_hidden_def(__xpg_strerror_r)