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