__xpg_strerror_r.c 4.5 KB

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