__xpg_strerror_r.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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. #if EDQUOT > 200 /* mips has an outrageous value for this... */
  143. 0,
  144. #else
  145. EDQUOT,
  146. #endif
  147. ENOMEDIUM,
  148. EMEDIUMTYPE,
  149. #if EDEADLOCK != EDEADLK
  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. #if EDQUOT > 200 /* Deal with large EDQUOT value on mips */
  173. if (errnum == EDQUOT)
  174. i = 122;
  175. #endif
  176. GOT_ESTRIDX:
  177. #else
  178. /* No errno to string index translation needed. */
  179. i = errnum;
  180. #endif
  181. if (((unsigned int) i) < _SYS_NERR) {
  182. /* Trade time for space. This function should rarely be called
  183. * so rather than keeping an array of pointers for the different
  184. * messages, just run through the buffer until we find the
  185. * correct string. */
  186. for (s = (char *) _string_syserrmsgs ; i ; ++s) {
  187. if (!*s) {
  188. --i;
  189. }
  190. }
  191. if (*s) { /* Make sure we have an actual message. */
  192. retval = 0;
  193. goto GOT_MESG;
  194. }
  195. }
  196. #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
  197. s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
  198. memcpy(s, unknown, sizeof(unknown));
  199. GOT_MESG:
  200. if (!strerrbuf) { /* SUSv3 */
  201. buflen = 0;
  202. }
  203. i = strlen(s) + 1;
  204. if (i > buflen) {
  205. i = buflen;
  206. retval = ERANGE;
  207. }
  208. if (i) {
  209. memcpy(strerrbuf, s, i);
  210. strerrbuf[i-1] = 0; /* In case buf was too small. */
  211. }
  212. if (retval) {
  213. __set_errno(retval);
  214. }
  215. return retval;
  216. }
  217. #else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
  218. int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
  219. {
  220. register char *s;
  221. int i, retval;
  222. char buf[_STRERROR_BUFSIZE];
  223. static const char unknown[] = {
  224. 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
  225. };
  226. s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
  227. memcpy(s, unknown, sizeof(unknown));
  228. if (!strerrbuf) { /* SUSv3 */
  229. buflen = 0;
  230. }
  231. retval = EINVAL;
  232. i = buf + sizeof(buf) - s;
  233. if (i > buflen) {
  234. i = buflen;
  235. retval = ERANGE;
  236. }
  237. if (i) {
  238. memcpy(strerrbuf, s, i);
  239. strerrbuf[i-1] = 0; /* In case buf was too small. */
  240. }
  241. __set_errno(retval);
  242. return retval;
  243. }
  244. #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
  245. libc_hidden_def(__xpg_strerror_r)