Fixed silc_errno_string to return correct error string.
[crypto.git] / lib / silcutil / silcerrno.c
1 /*
2
3   silcerrno.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 #include "silc.h"
21
22 /* Get last error */
23
24 SilcResult silc_get_errno(void)
25 {
26   SilcTls tls = silc_thread_get_tls();
27
28   if (!tls)
29     return SILC_OK;
30
31   return tls->error;
32 }
33
34 /* Set error */
35
36 void silc_set_errno(SilcResult error)
37 {
38   SilcTls tls = silc_thread_get_tls();
39
40   if (!tls) {
41     /* Try to create Tls */
42     tls = silc_thread_tls_init();
43     if (!tls)
44       return;
45   }
46
47   SILC_LOG_DEBUG(("Error: %s (%d)", silc_errno_string(error), error));
48
49   tls->error_reason[0] = '\0';
50   tls->error = error;
51 }
52
53 /* Set error, cannot fail. */
54
55 void silc_set_errno_nofail(SilcResult error)
56 {
57   SilcTls tls = silc_thread_get_tls();
58
59   if (!tls)
60     return;
61
62   SILC_LOG_DEBUG(("Error: %s (%d)", silc_errno_string(error), error));
63
64   tls->error_reason[0] = '\0';
65   tls->error = error;
66 }
67
68 /* Set errno and reason for error. */
69
70 void silc_set_errno_reason(SilcResult error, const char *format, ...)
71 {
72   SilcTls tls = silc_thread_get_tls();
73   va_list va;
74
75   if (!tls) {
76     /* Try to create Tls */
77     tls = silc_thread_tls_init();
78     if (!tls)
79       return;
80   }
81
82   va_start(va, format);
83   silc_vsnprintf(tls->error_reason, sizeof(tls->error_reason), format, va);
84   va_end(va);
85
86   SILC_LOG_DEBUG(("Error: %s (%d): %s", silc_errno_string(error), error,
87                   tls->error_reason));
88
89   tls->error = error;
90 }
91
92 /* Set errno and reason for error, cannot fail. */
93
94 void silc_set_errno_reason_nofail(SilcResult error, const char *format, ...)
95 {
96   SilcTls tls = silc_thread_get_tls();
97   va_list va;
98
99   if (!tls)
100     return;
101
102   va_start(va, format);
103   silc_vsnprintf(tls->error_reason, sizeof(tls->error_reason), format, va);
104   va_end(va);
105
106   SILC_LOG_DEBUG(("Error: %s (%d): %s", silc_errno_string(error), error,
107                   tls->error_reason));
108
109   tls->error = error;
110 }
111
112 /* Set error from POSIX errno. */
113
114 void silc_set_errno_posix(int error)
115 {
116   if (!error)
117     return;
118
119 #ifdef SILC_WIN32
120   /* WSA errors */
121   switch (error) {
122   case WSAEINTR:
123     silc_set_errno(SILC_ERR_INTERRUPTED);
124     break;
125   case WSAEBADF:
126     silc_set_errno(SILC_ERR_BAD_FD);
127     break;
128   case WSAEACCESS:
129     silc_set_errno(SILC_ERR_PERMISSION_DENIED);
130     break;
131   case WSAEFAULT:
132     silc_set_errno(SILC_ERR_BAD_ADDRESS);
133     break;
134   case WSA_INVALID_HANDLE:
135   case WSAENOTSOCK:
136     silc_set_errno(SILC_ERR_BAD_SOCKET);
137     break;
138   case WSA_INVALID_PARAMETER:
139   case WSAEINVAL:
140     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
141     break;
142   case WSA_NOT_ENOUGH_MEMORY:
143     silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
144     break;
145   case WSAEWOULDBLOCK:
146     silc_set_errno(SILC_ERR_WOULD_BLOCK);
147     break;
148   case WSAEOPNOTSUPPORT:
149     silc_set_errno(SILC_ERR_NOT_SUPPORTED);
150     break;
151   case WSAEADDRINUSE:
152     silc_set_errno(SILC_ERR_ADDR_IN_USE);
153     break;
154   case WSAEANETDOWN:
155     silc_set_errno(SILC_ERR_NET_DOWN);
156     break;
157   case WSAENETUNREACH:
158   case WSAEHOSTUNREACH:
159     silc_set_errno(SILC_ERR_UNREACHABLE);
160     break;
161   case WSAENETRESET:
162     silc_set_errno(SILC_ERR_RESET);
163     break;
164   case WSAECONNABORTED:
165     silc_set_errno(SILC_ERR_ABORTED);
166     break;
167   case WSAETIMEDOUT:
168     silc_set_errno(SILC_ERR_TIMEOUT);
169     break;
170   case WSAECONNREFUSED:
171     silc_set_errno(SILC_ERR_REFUSED);
172     break;
173   case WSAEHOSTDOWN:
174     silc_set_errno(SILC_ERR_HOST_DOWN);
175     break;
176   default:
177     silc_set_errno(SILC_ERR);
178     break;
179   }
180
181   return;
182 #endif /* SILC_WIN32 */
183
184   /* POSIX, etc. errors */
185   switch (error) {
186 #if defined(ENOMEM)
187   case ENOMEM:
188     silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
189     break;
190 #endif
191 #if defined(EAGAIN)
192   case EAGAIN:
193     silc_set_errno(SILC_ERR_WOULD_BLOCK);
194     break;
195 #endif
196 #if defined(EINVAL)
197   case EINVAL:
198     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
199     break;
200 #endif
201 #if defined(EINTR)
202   case EINTR:
203     silc_set_errno(SILC_ERR_INTERRUPTED);
204     break;
205 #endif
206 #if defined(EIO)
207   case EIO:
208     silc_set_errno(SILC_ERR_IO);
209     break;
210 #endif
211 #if defined(EPIPE)
212   case EPIPE:
213     silc_set_errno(SILC_ERR_BROKEN_PIPE);
214     break;
215 #endif
216 #if defined(ENOENT)
217   case ENOENT:
218     silc_set_errno(SILC_ERR_NO_SUCH_FILE);
219     break;
220 #endif
221 #if defined(EEXIST)
222   case EEXIST:
223     silc_set_errno(SILC_ERR_ALREADY_EXISTS);
224     break;
225 #endif
226 #if defined(ENOTDIR)
227   case ENOTDIR:
228     silc_set_errno(SILC_ERR_NOT_DIRECTORY);
229     break;
230 #endif
231 #if defined(EISDIR)
232   case EISDIR:
233     silc_set_errno(SILC_ERR_IS_DIRECTORY);
234     break;
235 #endif
236 #if defined(EBUSY)
237   case EBUSY:
238     silc_set_errno(SILC_ERR_BUSY);
239     break;
240 #endif
241 #if defined(ENODEV)
242   case ENODEV:
243     silc_set_errno(SILC_ERR_NO_SUCH_DEVICE);
244     break;
245 #endif
246 #if defined(ENOSPC)
247   case ENOSPC:
248     silc_set_errno(SILC_ERR_NO_SPACE_LEFT);
249     break;
250 #endif
251 #if defined(EROFS)
252   case EROFS:
253     silc_set_errno(SILC_ERR_READ_ONLY);
254     break;
255 #endif
256 #if defined(EBADFS)
257   case EBADFS:
258     silc_set_errno(SILC_ERR_BAD_FD);
259     break;
260 #endif
261 #if defined(EADDRINUSE)
262   case EADDRINUSE:
263     silc_set_errno(SILC_ERR_ADDR_IN_USE);
264     break;
265 #endif
266 #if defined(ECONNREFUSED)
267   case ECONNREFUSED:
268     silc_set_errno(SILC_ERR_REFUSED);
269     break;
270 #endif
271 #if defined(ECONNABORTED)
272   case ECONNABORTED:
273     silc_set_errno(SILC_ERR_ABORTED);
274     break;
275 #endif
276 #if defined(ECONNRESET)
277   case ECONNRESET:
278     silc_set_errno(SILC_ERR_RESET);
279     break;
280 #endif
281 #if defined(ENETUNREACH)
282   case ENETUNREACH:
283     silc_set_errno(SILC_ERR_UNREACHABLE);
284     break;
285 #endif
286 #if defined(EHOSTUNREACH)
287   case EHOSTUNREACH:
288     silc_set_errno(SILC_ERR_UNREACHABLE);
289     break;
290 #endif
291 #if defined(ENETDOWN)
292   case ENETDOWN:
293     silc_set_errno(SILC_ERR_NET_DOWN);
294     break;
295 #endif
296 #if defined(ETIMEDOUT)
297   case ETIMEDOUT:
298     silc_set_errno(SILC_ERR_TIMEOUT);
299     break;
300 #endif
301 #if defined(EHOSTDOWN)
302   case EHOSTDOWN:
303     silc_set_errno(SILC_ERR_HOST_DOWN);
304     break;
305 #endif
306   default:
307     silc_set_errno(SILC_ERR);
308     break;
309   }
310 }
311
312 /* Get last reason for error */
313
314 const char *silc_errno_reason(void)
315 {
316   SilcTls tls = silc_thread_get_tls();
317
318   if (!tls || tls->error_reason[0] == '\0')
319     return (const char *)"";
320
321   return tls->error_reason;
322 }
323
324 const char *silc_errno_strings[] =
325 {
326   "Ok",
327
328   "Error",
329   "Out of memory",
330   "Allocation by zero",
331   "Too large allocation",
332   "Overflow",
333   "Underflow",
334   "Feature not supported",
335   "Operation not permitted",
336   "Try again",
337   "Permission denied",
338   "Invalid argument",
339   "Bad time",
340   "Timeout",
341   "Assert",
342   "Not found",
343   "Unknown character",
344   "Prohibited character",
345   "Bad character encoding",
346   "Unsupported character encoding",
347   "Bad version",
348   "Bad memory address",
349   "Bad buffer encoding",
350   "Interrupted",
351   "Not valid",
352   "Limit reached",
353   "",
354   "",
355   "",
356   "",
357   "",
358   "",
359   "",
360   "",
361   "",
362   "",
363   "",
364   "",
365   "",
366   "",
367
368   "No such file or directory",
369   "Already exists",
370   "Not a directory",
371   "Is a directory",
372   "Directory not empty",
373   "Device or resource busy",
374   "No such device",
375   "No space left on device",
376   "Broken pipe",
377   "Read only",
378   "I/O error",
379   "Bad file descriptor",
380   "End of file",
381   "",
382   "",
383   "",
384   "",
385   "",
386   "",
387   "",
388   "",
389   "",
390   "",
391   "",
392   "",
393   "",
394   "",
395   "",
396   "",
397   "",
398
399   "Bad IP address",
400   "Unknown IP address",
401   "Unknown host",
402   "Destination unreachable",
403   "Connection refused",
404   "Connection aborted",
405   "Connection reset by peer",
406   "Would block",
407   "Host is down",
408   "Bad socket",
409   "Bad stream",
410   "Address already in use",
411   "Network is down",
412   "End of stream",
413
414   "",
415 };
416
417 /* Map error to string */
418
419 const char *silc_errno_string(SilcResult error)
420 {
421   if (error < 0 || error >= SILC_ERR_MAX)
422     return (const char *)"";
423
424   return silc_errno_strings[error];
425 }