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
8 /* get rid of REDIRECT */
9 #define strerror_r __hide_strerror_r
10
11 #include <features.h>
12 #include <errno.h>
13 #include <string.h>
14 #include "_syserrmsg.h"
15
16 #undef strerror_r
17
18 #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
19
20 extern const char _string_syserrmsgs[] attribute_hidden;
21
22 #if defined(__alpha__) || defined(__mips__) || defined(__sparc__)
23
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,
66 0,
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,
83 0,
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... */
148 0,
149 #else
150 EDQUOT,
151 #endif
152 ENOMEDIUM,
153 EMEDIUMTYPE,
154 #if EDEADLOCK != EDEADLK
155 EDEADLOCK,
156 #endif
157 };
158
159 #endif
160
__xpg_strerror_r(int errnum,char * strerrbuf,size_t buflen)161 int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
162 {
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', ' '
168 };
169
170 retval = EINVAL;
171
172
173 #ifdef __UCLIBC_HAS_ERRNO_MESSAGES__
174
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;
180 }
181 }
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
192
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;
201 }
202 }
203 if (*s) { /* Make sure we have an actual message. */
204 retval = 0;
205 goto GOT_MESG;
206 }
207 }
208
209 #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
210
211 s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
212 memcpy(s, unknown, sizeof(unknown));
213
214 GOT_MESG:
215 if (!strerrbuf) { /* SUSv3 */
216 buflen = 0;
217 }
218 i = strlen(s) + 1;
219 if (i > buflen) {
220 i = buflen;
221 retval = ERANGE;
222 }
223
224 if (i) {
225 memcpy(strerrbuf, s, i);
226 strerrbuf[i-1] = 0; /* In case buf was too small. */
227 }
228
229 if (retval) {
230 __set_errno(retval);
231 }
232
233 return retval;
234 }
235
236 #else /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
237
__xpg_strerror_r(int errnum,char * strerrbuf,size_t buflen)238 int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
239 {
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', ' '
245 };
246
247 s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
248 memcpy(s, unknown, sizeof(unknown));
249
250 if (!strerrbuf) { /* SUSv3 */
251 buflen = 0;
252 }
253
254 retval = EINVAL;
255
256 i = buf + sizeof(buf) - s;
257
258 if (i > buflen) {
259 i = buflen;
260 retval = ERANGE;
261 }
262
263 if (i) {
264 memcpy(strerrbuf, s, i);
265 strerrbuf[i-1] = 0; /* In case buf was too small. */
266 }
267
268 __set_errno(retval);
269
270 return retval;
271 }
272
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
278