__xpg_strerror_r.c 4.4 KB

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