Added silc_errno_set_location and silc_errno_location
[runtime.git] / lib / silcutil / silcerrno.c
1 /*
2
3   silcerrno.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2007 - 2008 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 "silcruntime.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   tls->error_reason[0] = '\0';
48   tls->filename[0] = '\0';
49   tls->error = error;
50 }
51
52 /* Set error, cannot fail. */
53
54 void silc_set_errno_nofail(SilcResult error)
55 {
56   SilcTls tls = silc_thread_get_tls();
57
58   if (!tls)
59     return;
60
61   tls->error_reason[0] = '\0';
62   tls->filename[0] = '\0';
63   tls->error = error;
64 }
65
66 /* Set errno and reason for error. */
67
68 void silc_set_errno_reason(SilcResult error, const char *format, ...)
69 {
70   SilcTls tls = silc_thread_get_tls();
71   va_list va;
72
73   if (!tls) {
74     /* Try to create Tls */
75     tls = silc_thread_tls_init();
76     if (!tls)
77       return;
78   }
79
80   if (format) {
81     va_start(va, format);
82     silc_vsnprintf(tls->error_reason, sizeof(tls->error_reason), format, va);
83     va_end(va);
84   }
85
86   tls->error = error;
87 }
88
89 /* Set errno and reason for error, cannot fail. */
90
91 void silc_set_errno_reason_nofail(SilcResult error, const char *format, ...)
92 {
93   SilcTls tls = silc_thread_get_tls();
94   va_list va;
95
96   if (!tls)
97     return;
98
99   if (format) {
100     va_start(va, format);
101     silc_vsnprintf(tls->error_reason, sizeof(tls->error_reason), format, va);
102     va_end(va);
103   }
104
105   tls->error = error;
106 }
107
108 /* Set error from POSIX errno. */
109
110 void silc_set_errno_posix(int error)
111 {
112   if (!error)
113     return;
114
115 #ifdef SILC_WIN32
116   /* WSA errors */
117   switch (error) {
118   case WSAEINTR:
119     silc_set_errno(SILC_ERR_INTERRUPTED);
120     break;
121   case WSAEBADF:
122     silc_set_errno(SILC_ERR_BAD_FD);
123     break;
124   case WSAEACCESS:
125     silc_set_errno(SILC_ERR_PERMISSION_DENIED);
126     break;
127   case WSAEFAULT:
128     silc_set_errno(SILC_ERR_BAD_ADDRESS);
129     break;
130   case WSA_INVALID_HANDLE:
131   case WSAENOTSOCK:
132     silc_set_errno(SILC_ERR_BAD_SOCKET);
133     break;
134   case WSA_INVALID_PARAMETER:
135   case WSAEINVAL:
136     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
137     break;
138   case WSA_NOT_ENOUGH_MEMORY:
139     silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
140     break;
141   case WSAEWOULDBLOCK:
142     silc_set_errno(SILC_ERR_WOULD_BLOCK);
143     break;
144   case WSAEOPNOTSUPPORT:
145     silc_set_errno(SILC_ERR_NOT_SUPPORTED);
146     break;
147   case WSAEADDRINUSE:
148     silc_set_errno(SILC_ERR_ADDR_IN_USE);
149     break;
150   case WSAEANETDOWN:
151     silc_set_errno(SILC_ERR_NET_DOWN);
152     break;
153   case WSAENETUNREACH:
154   case WSAEHOSTUNREACH:
155     silc_set_errno(SILC_ERR_UNREACHABLE);
156     break;
157   case WSAENETRESET:
158     silc_set_errno(SILC_ERR_RESET);
159     break;
160   case WSAECONNABORTED:
161     silc_set_errno(SILC_ERR_ABORTED);
162     break;
163   case WSAETIMEDOUT:
164     silc_set_errno(SILC_ERR_TIMEOUT);
165     break;
166   case WSAECONNREFUSED:
167     silc_set_errno(SILC_ERR_REFUSED);
168     break;
169   case WSAEHOSTDOWN:
170     silc_set_errno(SILC_ERR_HOST_DOWN);
171     break;
172   default:
173     silc_set_errno(SILC_ERR);
174     break;
175   }
176
177   return;
178 #endif /* SILC_WIN32 */
179
180   /* POSIX, etc. errors */
181   switch (error) {
182 #if defined(ENOMEM)
183   case ENOMEM:
184     silc_set_errno(SILC_ERR_OUT_OF_MEMORY);
185     break;
186 #endif
187 #if defined(EAGAIN)
188   case EAGAIN:
189     silc_set_errno(SILC_ERR_WOULD_BLOCK);
190     break;
191 #endif
192 #if defined(EINVAL)
193   case EINVAL:
194     silc_set_errno(SILC_ERR_INVALID_ARGUMENT);
195     break;
196 #endif
197 #if defined(EINTR)
198   case EINTR:
199     silc_set_errno(SILC_ERR_INTERRUPTED);
200     break;
201 #endif
202 #if defined(EIO)
203   case EIO:
204     silc_set_errno(SILC_ERR_IO);
205     break;
206 #endif
207 #if defined(EPIPE)
208   case EPIPE:
209     silc_set_errno(SILC_ERR_BROKEN_PIPE);
210     break;
211 #endif
212 #if defined(ENOENT)
213   case ENOENT:
214     silc_set_errno(SILC_ERR_NO_SUCH_FILE);
215     break;
216 #endif
217 #if defined(EEXIST)
218   case EEXIST:
219     silc_set_errno(SILC_ERR_ALREADY_EXISTS);
220     break;
221 #endif
222 #if defined(ENOTDIR)
223   case ENOTDIR:
224     silc_set_errno(SILC_ERR_NOT_DIRECTORY);
225     break;
226 #endif
227 #if defined(EISDIR)
228   case EISDIR:
229     silc_set_errno(SILC_ERR_IS_DIRECTORY);
230     break;
231 #endif
232 #if defined(EBUSY)
233   case EBUSY:
234     silc_set_errno(SILC_ERR_BUSY);
235     break;
236 #endif
237 #if defined(ENODEV)
238   case ENODEV:
239     silc_set_errno(SILC_ERR_NO_SUCH_DEVICE);
240     break;
241 #endif
242 #if defined(ENOSPC)
243   case ENOSPC:
244     silc_set_errno(SILC_ERR_NO_SPACE_LEFT);
245     break;
246 #endif
247 #if defined(EROFS)
248   case EROFS:
249     silc_set_errno(SILC_ERR_READ_ONLY);
250     break;
251 #endif
252 #if defined(EBADFS)
253   case EBADFS:
254     silc_set_errno(SILC_ERR_BAD_FD);
255     break;
256 #endif
257 #if defined(EADDRINUSE)
258   case EADDRINUSE:
259     silc_set_errno(SILC_ERR_ADDR_IN_USE);
260     break;
261 #endif
262 #if defined(ECONNREFUSED)
263   case ECONNREFUSED:
264     silc_set_errno(SILC_ERR_REFUSED);
265     break;
266 #endif
267 #if defined(ECONNABORTED)
268   case ECONNABORTED:
269     silc_set_errno(SILC_ERR_ABORTED);
270     break;
271 #endif
272 #if defined(ECONNRESET)
273   case ECONNRESET:
274     silc_set_errno(SILC_ERR_RESET);
275     break;
276 #endif
277 #if defined(ENETUNREACH)
278   case ENETUNREACH:
279     silc_set_errno(SILC_ERR_UNREACHABLE);
280     break;
281 #endif
282 #if defined(EHOSTUNREACH)
283   case EHOSTUNREACH:
284     silc_set_errno(SILC_ERR_UNREACHABLE);
285     break;
286 #endif
287 #if defined(ENETDOWN)
288   case ENETDOWN:
289     silc_set_errno(SILC_ERR_NET_DOWN);
290     break;
291 #endif
292 #if defined(ETIMEDOUT)
293   case ETIMEDOUT:
294     silc_set_errno(SILC_ERR_TIMEOUT);
295     break;
296 #endif
297 #if defined(EHOSTDOWN)
298   case EHOSTDOWN:
299     silc_set_errno(SILC_ERR_HOST_DOWN);
300     break;
301 #endif
302   default:
303     silc_set_errno(SILC_ERR);
304     break;
305   }
306 }
307
308 /* Get last reason for error */
309
310 const char *silc_errno_reason(void)
311 {
312   SilcTls tls = silc_thread_get_tls();
313
314   if (!tls || tls->error_reason[0] == '\0')
315     return (const char *)"";
316
317   return tls->error_reason;
318 }
319
320 const char *silc_errno_strings[] =
321 {
322   "Ok",
323
324   "Error",
325   "Out of memory",
326   "Allocation by zero",
327   "Too large allocation",
328   "Overflow",
329   "Underflow",
330   "Feature not supported",
331   "Operation not permitted",
332   "Try again",
333   "Permission denied",
334   "Invalid argument",
335   "Bad time",
336   "Timeout",
337   "Assert",
338   "Not found",
339   "Unknown character",
340   "Prohibited character",
341   "Bad character encoding",
342   "Unsupported character encoding",
343   "Bad version",
344   "Bad memory address",
345   "Bad buffer encoding",
346   "Interrupted",
347   "Not valid",
348   "Limit reached",
349   "Syntax error",
350   "",
351   "",
352   "",
353   "",
354   "",
355   "",
356   "",
357   "",
358   "",
359   "",
360   "",
361   "",
362   "",
363
364   "No such file or directory",
365   "Already exists",
366   "Not a directory",
367   "Is a directory",
368   "Directory not empty",
369   "Device or resource busy",
370   "No such device",
371   "No space left on device",
372   "Broken pipe",
373   "Read only",
374   "I/O error",
375   "Bad file descriptor",
376   "End of file",
377   "",
378   "",
379   "",
380   "",
381   "",
382   "",
383   "",
384   "",
385   "",
386   "",
387   "",
388   "",
389   "",
390   "",
391   "",
392   "",
393   "",
394
395   "Bad IP address",
396   "Unknown IP address",
397   "Unknown host",
398   "Destination unreachable",
399   "Connection refused",
400   "Connection aborted",
401   "Connection reset by peer",
402   "Would block",
403   "Host is down",
404   "Bad socket",
405   "Bad stream",
406   "Address already in use",
407   "Network is down",
408   "End of stream",
409   "",
410   "",
411   "",
412   "",
413   "",
414   "",
415   "",
416   "",
417   "",
418   "",
419   "",
420   "",
421   "",
422   "",
423   "",
424   "",
425
426   "Badly placed parenthesis",
427   "Bad hexadecimal number",
428   "Bad match register number",
429   "Badly placed special character",
430   "Regular expression too complex",
431   "Bad regular expression opcode",
432   "Bad repeat value",
433 };
434
435 /* Map error to string */
436
437 const char *silc_errno_string(SilcResult error)
438 {
439   if (error < 0 || error >= SILC_ERR_MAX)
440     return (const char *)"";
441
442   return silc_errno_strings[error];
443 }
444
445 /* Set error location */
446
447 void silc_set_errno_location(const char *filename,
448                              SilcUInt32 current_line_number,
449                              SilcUInt32 current_column_number)
450 {
451   SilcTls tls = silc_thread_get_tls();
452
453   if (!tls)
454     return;
455
456   if (filename)
457     silc_snprintf(tls->filename, sizeof(tls->filename), filename);
458   tls->cur_line = current_line_number;
459   tls->cur_column = current_column_number;
460 }
461
462 /* Get error location */
463
464 SilcBool silc_errno_location(const char **filename,
465                              SilcUInt32 *current_line,
466                              SilcUInt32 *current_column)
467 {
468   SilcTls tls = silc_thread_get_tls();
469
470   if (!tls)
471     return FALSE;
472   if (tls->filename[0] == '\0' && !tls->cur_line && !tls->cur_column)
473     return FALSE;
474
475   if (filename)
476     *filename = tls->filename;
477   if (current_line)
478     *current_line = tls->cur_line;
479   if (current_column)
480     *current_column = tls->cur_column;
481
482   return TRUE;
483 }