merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mono / io-layer / error.c
1 /*
2  * error.c:  Error reporting
3  *
4  * Author:
5  *      Dick Porter (dick@ximian.com)
6  *
7  * (C) 2002 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #include <glib.h>
12 #include <pthread.h>
13 #include <string.h>
14 #include <errno.h>
15
16 #include "mono/io-layer/wapi.h"
17
18 static pthread_key_t error_key;
19 static mono_once_t error_key_once=MONO_ONCE_INIT;
20
21 static void error_init(void)
22 {
23         int ret;
24         
25         ret = pthread_key_create(&error_key, NULL);
26         g_assert (ret == 0);
27 }
28
29 /**
30  * GetLastError:
31  *
32  * Retrieves the last error that occurred in the calling thread.
33  *
34  * Return value: The error code for the last error that happened on
35  * the calling thread.
36  */
37 guint32 GetLastError(void)
38 {
39         guint32 err;
40         void *errptr;
41         
42         mono_once(&error_key_once, error_init);
43         errptr=pthread_getspecific(error_key);
44         err=GPOINTER_TO_UINT(errptr);
45         
46         return(err);
47 }
48
49 /**
50  * SetLastError:
51  * @code: The error code.
52  *
53  * Sets the error code in the calling thread.
54  */
55 void SetLastError(guint32 code)
56 {
57         int ret;
58         
59         /* Set the thread-local error code */
60         mono_once(&error_key_once, error_init);
61         ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
62         g_assert (ret == 0);
63 }
64
65 guint32
66 errno_to_WSA (guint32 code, const gchar *function_name)
67 {
68         gint result = -1;
69         char *sys_error;
70         gchar *msg;
71
72         switch (code) {
73         case 0: result = ERROR_SUCCESS; break;
74         case EACCES: result = WSAEACCES; break;
75         case EADDRINUSE: result = WSAEADDRINUSE; break;
76         case EAFNOSUPPORT: result = WSAEAFNOSUPPORT; break;
77 #if EAGAIN != EWOULDBLOCK
78         case EAGAIN: result = WSAEWOULDBLOCK; break;
79 #endif
80         case EALREADY: result = WSAEALREADY; break;
81         case EBADF: result = WSAENOTSOCK; break;
82         case ECONNABORTED: result = WSAENETDOWN; break;
83         case ECONNREFUSED: result = WSAECONNREFUSED; break;
84         case ECONNRESET: result = WSAECONNRESET; break;
85         case EFAULT: result = WSAEFAULT; break;
86         case EHOSTUNREACH: result = WSAEHOSTUNREACH; break;
87         case EINPROGRESS: result = WSAEINPROGRESS; break;
88         case EINTR: result = WSAEINTR; break;
89         case EINVAL: result = WSAEINVAL; break;
90         /*FIXME: case EIO: result = WSAE????; break; */
91         case EISCONN: result = WSAEISCONN; break;
92         /* FIXME: case ELOOP: result = WSA????; break; */
93         case EMFILE: result = WSAEMFILE; break;
94         case EMSGSIZE: result = WSAEMSGSIZE; break;
95         /* FIXME: case ENAMETOOLONG: result = WSAEACCES; break; */
96         case ENETUNREACH: result = WSAENETUNREACH; break;
97         case ENOBUFS: result = WSAENOBUFS; break; /* not documented */
98         /* case ENOENT: result = WSAE????; break; */
99         case ENOMEM: result = WSAENOBUFS; break;
100         case ENOPROTOOPT: result = WSAENOPROTOOPT; break;
101 #ifdef ENOSR
102         case ENOSR: result = WSAENETDOWN; break;
103 #endif
104         case ENOTCONN: result = WSAENOTCONN; break;
105         /*FIXME: case ENOTDIR: result = WSAE????; break; */
106         case ENOTSOCK: result = WSAENOTSOCK; break;
107         case ENOTTY: result = WSAENOTSOCK; break;
108         case EOPNOTSUPP: result = WSAEOPNOTSUPP; break;
109         case EPERM: result = WSAEACCES; break;
110         case EPIPE: result = WSAESHUTDOWN; break;
111         case EPROTONOSUPPORT: result = WSAEPROTONOSUPPORT; break;
112 #if ERESTARTSYS
113         case ERESTARTSYS: result = WSAENETDOWN; break;
114 #endif
115         /*FIXME: case EROFS: result = WSAE????; break; */
116         case ESOCKTNOSUPPORT: result = WSAESOCKTNOSUPPORT; break;
117         case ETIMEDOUT: result = WSAENETDOWN; break;
118         case EWOULDBLOCK: result = WSAEWOULDBLOCK; break;
119         case EADDRNOTAVAIL: result = WSAEADDRNOTAVAIL; break;
120         /* This might happen with unix sockets */
121         case ENOENT: result = WSAECONNREFUSED; break;
122         default:
123                 sys_error = strerror (code);
124                 msg = g_locale_to_utf8 (sys_error, strlen (sys_error), NULL, NULL, NULL);
125                 if (function_name == NULL)
126                         function_name = __func__;
127
128                 g_warning ("%s: Need to translate %d [%s] into winsock error",
129                            function_name, code, msg);
130
131                 g_free (msg);
132                 result = WSASYSCALLFAILURE;
133         }
134
135         return result;
136 }
137
138 gint
139 _wapi_get_win32_file_error (gint err)
140 {
141         gint ret;
142         /* mapping ideas borrowed from wine. they may need some work */
143
144         switch (err) {
145         case EACCES: case EPERM: case EROFS:
146                 ret = ERROR_ACCESS_DENIED;
147                 break;
148         
149         case EAGAIN:
150                 ret = ERROR_SHARING_VIOLATION;
151                 break;
152         
153         case EBUSY:
154                 ret = ERROR_LOCK_VIOLATION;
155                 break;
156         
157         case EEXIST:
158                 ret = ERROR_FILE_EXISTS;
159                 break;
160         
161         case EINVAL: case ESPIPE:
162                 ret = ERROR_SEEK;
163                 break;
164         
165         case EISDIR:
166                 ret = ERROR_CANNOT_MAKE;
167                 break;
168         
169         case ENFILE: case EMFILE:
170                 ret = ERROR_TOO_MANY_OPEN_FILES;
171                 break;
172
173         case ENOENT: case ENOTDIR:
174                 ret = ERROR_FILE_NOT_FOUND;
175                 break;
176         
177         case ENOSPC:
178                 ret = ERROR_HANDLE_DISK_FULL;
179                 break;
180         
181         case ENOTEMPTY:
182                 ret = ERROR_DIR_NOT_EMPTY;
183                 break;
184
185         case ENOEXEC:
186                 ret = ERROR_BAD_FORMAT;
187                 break;
188
189         case ENAMETOOLONG:
190                 ret = ERROR_FILENAME_EXCED_RANGE;
191                 break;
192         
193         case EINPROGRESS:
194                 ret = ERROR_IO_PENDING;
195                 break;
196         
197         case ENOSYS:
198                 ret = ERROR_NOT_SUPPORTED;
199                 break;
200         
201         case EBADF:
202                 ret = ERROR_INVALID_HANDLE;
203                 break;
204                 
205         case EIO:
206                 ret = ERROR_INVALID_HANDLE;
207                 break;
208                 
209         case EINTR:
210                 ret = ERROR_IO_PENDING;         /* best match I could find */
211                 break;
212                 
213         case EPIPE:
214                 ret = ERROR_WRITE_FAULT;
215                 break;
216                 
217         default:
218                 g_message ("Unknown errno: %s\n", g_strerror (err));
219                 ret = ERROR_GEN_FAILURE;
220                 break;
221         }
222
223         return ret;
224 }
225