[io-layer] Extract socket (#4241)
[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 #include "mono/io-layer/wapi-private.h"
18 #include "mono/utils/mono-lazy-init.h"
19
20 static pthread_key_t error_key;
21 static mono_lazy_init_t error_key_once = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
22
23 static void error_init(void)
24 {
25         int ret;
26         
27         ret = pthread_key_create(&error_key, NULL);
28         g_assert (ret == 0);
29 }
30
31 static void error_cleanup (void)
32 {
33         int ret;
34
35         ret = pthread_key_delete (error_key);
36         g_assert (ret == 0);
37 }
38
39 void _wapi_error_cleanup (void)
40 {
41         mono_lazy_cleanup (&error_key_once, error_cleanup);
42 }
43
44 /**
45  * GetLastError:
46  *
47  * Retrieves the last error that occurred in the calling thread.
48  *
49  * Return value: The error code for the last error that happened on
50  * the calling thread.
51  */
52 guint32 GetLastError(void)
53 {
54         guint32 err;
55         void *errptr;
56
57         if (_wapi_has_shut_down)
58                 return 0;
59         mono_lazy_initialize(&error_key_once, error_init);
60         errptr=pthread_getspecific(error_key);
61         err=GPOINTER_TO_UINT(errptr);
62         
63         return(err);
64 }
65
66 /**
67  * SetLastError:
68  * @code: The error code.
69  *
70  * Sets the error code in the calling thread.
71  */
72 void SetLastError(guint32 code)
73 {
74         int ret;
75         
76         if (_wapi_has_shut_down)
77                 return;
78         /* Set the thread-local error code */
79         mono_lazy_initialize(&error_key_once, error_init);
80         ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code));
81         g_assert (ret == 0);
82 }
83
84 gint
85 _wapi_get_win32_file_error (gint err)
86 {
87         gint ret;
88         /* mapping ideas borrowed from wine. they may need some work */
89
90         switch (err) {
91         case EACCES: case EPERM: case EROFS:
92                 ret = ERROR_ACCESS_DENIED;
93                 break;
94         
95         case EAGAIN:
96                 ret = ERROR_SHARING_VIOLATION;
97                 break;
98         
99         case EBUSY:
100                 ret = ERROR_LOCK_VIOLATION;
101                 break;
102         
103         case EEXIST:
104                 ret = ERROR_FILE_EXISTS;
105                 break;
106         
107         case EINVAL: case ESPIPE:
108                 ret = ERROR_SEEK;
109                 break;
110         
111         case EISDIR:
112                 ret = ERROR_CANNOT_MAKE;
113                 break;
114         
115         case ENFILE: case EMFILE:
116                 ret = ERROR_TOO_MANY_OPEN_FILES;
117                 break;
118
119         case ENOENT: case ENOTDIR:
120                 ret = ERROR_FILE_NOT_FOUND;
121                 break;
122         
123         case ENOSPC:
124                 ret = ERROR_HANDLE_DISK_FULL;
125                 break;
126         
127         case ENOTEMPTY:
128                 ret = ERROR_DIR_NOT_EMPTY;
129                 break;
130
131         case ENOEXEC:
132                 ret = ERROR_BAD_FORMAT;
133                 break;
134
135         case ENAMETOOLONG:
136                 ret = ERROR_FILENAME_EXCED_RANGE;
137                 break;
138         
139 #ifdef EINPROGRESS
140         case EINPROGRESS:
141                 ret = ERROR_IO_PENDING;
142                 break;
143 #endif
144         
145         case ENOSYS:
146                 ret = ERROR_NOT_SUPPORTED;
147                 break;
148         
149         case EBADF:
150                 ret = ERROR_INVALID_HANDLE;
151                 break;
152                 
153         case EIO:
154                 ret = ERROR_INVALID_HANDLE;
155                 break;
156                 
157         case EINTR:
158                 ret = ERROR_IO_PENDING;         /* best match I could find */
159                 break;
160                 
161         case EPIPE:
162                 ret = ERROR_WRITE_FAULT;
163                 break;
164                 
165         default:
166                 g_message ("Unknown errno: %s\n", g_strerror (err));
167                 ret = ERROR_GEN_FAILURE;
168                 break;
169         }
170
171         return ret;
172 }
173