OSDN Git Service

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