OSDN Git Service

hidden_def/hidden_proto: convert all users (I hope) termios split, add some missing...
[uclinux-h8/uClibc.git] / libc / string / __xpg_strerror_r.c
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
8 #define _GNU_SOURCE
9 #include <features.h>
10 #include <errno.h>
11 #include <string.h>
12 #include <bits/uClibc_uintmaxtostr.h>
13 #include "_syserrmsg.h"
14
15 libc_hidden_proto(__xpg_strerror_r)
16 libc_hidden_proto(memcpy)
17 libc_hidden_proto(strlen)
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 #ifdef __mips__
149         0,                                                      /* mips has an outrageous value for this... */
150 #else
151         EDQUOT,
152 #endif
153         ENOMEDIUM,
154         EMEDIUMTYPE,
155 #if defined(__mips__) || defined(__sparc__)
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 #ifdef __mips__
185         if (errnum == EDQUOT) { /* Deal with large EDQUOT value on mips */
186                 i = 122;
187         }
188 #endif /* __mips__ */
189  GOT_ESTRIDX:
190 #else
191         /* No errno to string index translation needed. */
192         i = errnum;
193 #endif
194
195     if (((unsigned int) i) < _SYS_NERR) {
196                 /* Trade time for space.  This function should rarely be called
197                  * so rather than keeping an array of pointers for the different
198                  * messages, just run through the buffer until we find the
199                  * correct string. */
200                 for (s = (char *) _string_syserrmsgs ; i ; ++s) {
201                         if (!*s) {
202                                 --i;
203                         }
204                 }
205                 if (*s) {               /* Make sure we have an actual message. */
206                         retval = 0;
207                         goto GOT_MESG;
208                 }
209     }
210
211 #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
212
213     s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
214     memcpy(s, unknown, sizeof(unknown));
215
216  GOT_MESG:
217     if (!strerrbuf) {           /* SUSv3  */
218                 buflen = 0;
219     }
220     i = strlen(s) + 1;
221     if (i > buflen) {
222                 i = buflen;
223                 retval = ERANGE;
224     }
225
226     if (i) {
227                 memcpy(strerrbuf, s, i);
228                 strerrbuf[i-1] = 0;     /* In case buf was too small. */
229     }
230
231     if (retval) {
232                 __set_errno(retval);
233     }
234
235     return retval;
236 }
237
238 #else  /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
239
240 int __xpg_strerror_r(int errnum, char *strerrbuf, size_t buflen)
241 {
242     register char *s;
243     int i, retval;
244     char buf[_STRERROR_BUFSIZE];
245     static const char unknown[] = {
246                 'U', 'n', 'k', 'n', 'o', 'w', 'n', ' ', 'e', 'r', 'r', 'o', 'r', ' '
247     };
248
249     s = _int10tostr(buf+sizeof(buf)-1, errnum) - sizeof(unknown);
250     memcpy(s, unknown, sizeof(unknown));
251
252     if (!strerrbuf) {           /* SUSv3  */
253                 buflen = 0;
254     }
255
256     retval = EINVAL;
257
258         i = buf + sizeof(buf) - s;
259
260     if (i > buflen) {
261                 i = buflen;
262                 retval = ERANGE;
263     }
264
265     if (i) {
266                 memcpy(strerrbuf, s, i);
267                 strerrbuf[i-1] = 0;     /* In case buf was too small. */
268     }
269
270         __set_errno(retval);
271
272     return retval;
273 }
274
275 #endif /* __UCLIBC_HAS_ERRNO_MESSAGES__ */
276 libc_hidden_def(__xpg_strerror_r)