__xpg_strerror_r.c 4.5 KB

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