__xpg_strerror_r.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * Copyright (C) 2002 Manuel Novoa III
  3. * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
  4. *
  5. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  6. */
  7. /* Make sure we get proper strerror_r() prototype */
  8. #define strerror_r __moo
  9. #include <features.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include "_syserrmsg.h"
  13. #undef strerror_r
  14. libc_hidden_proto(__xpg_strerror_r)
  15. /* Experimentally off - libc_hidden_proto(memcpy) */
  16. /* Experimentally off - libc_hidden_proto(strlen) */
  17. #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
  18. extern const char _string_syserrmsgs[] attribute_hidden;
  19. #if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
  20. static const unsigned char estridx[] = {
  21. 0, /* success is always 0 */
  22. EPERM,
  23. ENOENT,
  24. ESRCH,
  25. EINTR,
  26. EIO,
  27. ENXIO,
  28. E2BIG,
  29. ENOEXEC,
  30. EBADF,
  31. ECHILD,
  32. EAGAIN,
  33. ENOMEM,
  34. EACCES,
  35. EFAULT,
  36. ENOTBLK,
  37. EBUSY,
  38. EEXIST,
  39. EXDEV,
  40. ENODEV,
  41. ENOTDIR,
  42. EISDIR,
  43. EINVAL,
  44. ENFILE,
  45. EMFILE,
  46. ENOTTY,
  47. ETXTBSY,
  48. EFBIG,
  49. ENOSPC,
  50. ESPIPE,
  51. EROFS,
  52. EMLINK,
  53. EPIPE,
  54. EDOM,
  55. ERANGE,
  56. EDEADLK,
  57. ENAMETOOLONG,
  58. ENOLCK,
  59. ENOSYS,
  60. ENOTEMPTY,
  61. ELOOP,
  62. 0,
  63. ENOMSG,
  64. EIDRM,
  65. ECHRNG,
  66. EL2NSYNC,
  67. EL3HLT,
  68. EL3RST,
  69. ELNRNG,
  70. EUNATCH,
  71. ENOCSI,
  72. EL2HLT,
  73. EBADE,
  74. EBADR,
  75. EXFULL,
  76. ENOANO,
  77. EBADRQC,
  78. EBADSLT,
  79. 0,
  80. EBFONT,
  81. ENOSTR,
  82. ENODATA,
  83. ETIME,
  84. ENOSR,
  85. ENONET,
  86. ENOPKG,
  87. EREMOTE,
  88. ENOLINK,
  89. EADV,
  90. ESRMNT,
  91. ECOMM,
  92. EPROTO,
  93. EMULTIHOP,
  94. EDOTDOT,
  95. EBADMSG,
  96. EOVERFLOW,
  97. ENOTUNIQ,
  98. EBADFD,
  99. EREMCHG,
  100. ELIBACC,
  101. ELIBBAD,
  102. ELIBSCN,
  103. ELIBMAX,
  104. ELIBEXEC,
  105. EILSEQ,
  106. ERESTART,
  107. ESTRPIPE,
  108. EUSERS,
  109. ENOTSOCK,
  110. EDESTADDRREQ,
  111. EMSGSIZE,
  112. EPROTOTYPE,
  113. ENOPROTOOPT,
  114. EPROTONOSUPPORT,
  115. ESOCKTNOSUPPORT,
  116. EOPNOTSUPP,
  117. EPFNOSUPPORT,
  118. EAFNOSUPPORT,
  119. EADDRINUSE,
  120. EADDRNOTAVAIL,
  121. ENETDOWN,
  122. ENETUNREACH,
  123. ENETRESET,
  124. ECONNABORTED,
  125. ECONNRESET,
  126. ENOBUFS,
  127. EISCONN,
  128. ENOTCONN,
  129. ESHUTDOWN,
  130. ETOOMANYREFS,
  131. ETIMEDOUT,
  132. ECONNREFUSED,
  133. EHOSTDOWN,
  134. EHOSTUNREACH,
  135. EALREADY,
  136. EINPROGRESS,
  137. ESTALE,
  138. EUCLEAN,
  139. ENOTNAM,
  140. ENAVAIL,
  141. EISNAM,
  142. EREMOTEIO,
  143. #if EDQUOT > 200 /* mips has an outrageous value for this... */
  144. 0,
  145. #else
  146. EDQUOT,
  147. #endif
  148. ENOMEDIUM,
  149. EMEDIUMTYPE,
  150. #if EDEADLOCK != EDEADLK
  151. EDEADLOCK,
  152. #endif
  153. };
  154. #endif
  155. int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
  156. {
  157. register char *s;
  158. int i, retval;
  159. char buf[_STRERROR_BUFSIZE];
  160. static const char unknown[] = {
  161. 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
  162. };
  163. retval = EINVAL;
  164. #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
  165. #if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
  166. /* Need to translate errno to string index. */
  167. for (i = 0 ; i < sizeof(estridx)/sizeof(estridx[0]) ; i++) {
  168. if (estridx[i] == errnum) {
  169. goto GOT_ESTRIDX;
  170. }
  171. }
  172. i = INT_MAX; /* Failed, but may need to check mips special case. */
  173. #if EDQUOT > 200 /* Deal with large EDQUOT value on mips */
  174. if (errnum == EDQUOT)
  175. i = 122;
  176. #endif
  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)
  247. weak_alias(__xpg_strerror_r, strerror_r)