1
/* Ocaml does not provide an API for interfacing with the Unix
2
library from a FFI. This is especially problematic on Win32,
3
because the unixsupport functions are not even exported.
4
Because of this, here is a copy of unixsupport.c (win32 variant).
6
To avoid name clashes, some functions have got a prefix (netsysw32_).
7
The "#include" lines are adapted. cst_to_constr and
8
unix_error_of_code have been added.
11
/***********************************************************************/
15
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
17
/* Copyright 1996 Institut National de Recherche en Informatique et */
18
/* en Automatique. All rights reserved. This file is distributed */
19
/* under the terms of the GNU Library General Public License, with */
20
/* the special exception on linking described in file ../../LICENSE. */
22
/***********************************************************************/
24
/* $Id: unixsupport.c,v 1.20 2005/09/22 14:21:50 xleroy Exp $ */
26
static value cst_to_constr(int n, int *tbl, int size, int deflt)
29
for (i = 0; i < size; i++)
30
if (n == tbl[i]) return Val_int(i);
31
return Val_int(deflt);
34
/* Heap-allocation of Windows file handles */
36
static int win_handle_compare(value v1, value v2)
38
HANDLE h1 = Handle_val(v1);
39
HANDLE h2 = Handle_val(v2);
40
return h1 == h2 ? 0 : h1 < h2 ? -1 : 1;
43
static intnat win_handle_hash(value v)
45
return (intnat) Handle_val(v);
48
static struct custom_operations win_handle_ops = {
50
custom_finalize_default,
53
custom_serialize_default,
54
custom_deserialize_default
57
value netsysw32_win_alloc_handle(HANDLE h)
59
value res = alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1);
61
Descr_kind_val(res) = KIND_HANDLE;
62
CRT_fd_val(res) = NO_CRT_FD;
66
value netsysw32_win_alloc_socket(SOCKET s)
68
value res = alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1);
70
Descr_kind_val(res) = KIND_SOCKET;
71
CRT_fd_val(res) = NO_CRT_FD;
75
value netsysw32_win_alloc_handle_or_socket(HANDLE h)
77
value res = win_alloc_handle(h);
79
int optlen = sizeof(opt);
80
if (getsockopt((SOCKET) h, SOL_SOCKET, SO_TYPE, (char *)&opt, &optlen) == 0)
81
Descr_kind_val(res) = KIND_SOCKET;
85
/* Mapping of Windows error codes to POSIX error codes */
87
struct error_entry { DWORD win_code; int range; int posix_code; };
89
static struct error_entry win_error_table[] = {
90
{ ERROR_INVALID_FUNCTION, 0, EINVAL},
91
{ ERROR_FILE_NOT_FOUND, 0, ENOENT},
92
{ ERROR_PATH_NOT_FOUND, 0, ENOENT},
93
{ ERROR_TOO_MANY_OPEN_FILES, 0, EMFILE},
94
{ ERROR_ACCESS_DENIED, 0, EACCES},
95
{ ERROR_INVALID_HANDLE, 0, EBADF},
96
{ ERROR_ARENA_TRASHED, 0, ENOMEM},
97
{ ERROR_NOT_ENOUGH_MEMORY, 0, ENOMEM},
98
{ ERROR_INVALID_BLOCK, 0, ENOMEM},
99
{ ERROR_BAD_ENVIRONMENT, 0, E2BIG},
100
{ ERROR_BAD_FORMAT, 0, ENOEXEC},
101
{ ERROR_INVALID_ACCESS, 0, EINVAL},
102
{ ERROR_INVALID_DATA, 0, EINVAL},
103
{ ERROR_INVALID_DRIVE, 0, ENOENT},
104
{ ERROR_CURRENT_DIRECTORY, 0, EACCES},
105
{ ERROR_NOT_SAME_DEVICE, 0, EXDEV},
106
{ ERROR_NO_MORE_FILES, 0, ENOENT},
107
{ ERROR_LOCK_VIOLATION, 0, EACCES},
108
{ ERROR_BAD_NETPATH, 0, ENOENT},
109
{ ERROR_NETWORK_ACCESS_DENIED, 0, EACCES},
110
{ ERROR_BAD_NET_NAME, 0, ENOENT},
111
{ ERROR_FILE_EXISTS, 0, EEXIST},
112
{ ERROR_CANNOT_MAKE, 0, EACCES},
113
{ ERROR_FAIL_I24, 0, EACCES},
114
{ ERROR_INVALID_PARAMETER, 0, EINVAL},
115
{ ERROR_NO_PROC_SLOTS, 0, EAGAIN},
116
{ ERROR_DRIVE_LOCKED, 0, EACCES},
117
{ ERROR_BROKEN_PIPE, 0, EPIPE},
118
{ ERROR_DISK_FULL, 0, ENOSPC},
119
{ ERROR_INVALID_TARGET_HANDLE, 0, EBADF},
120
{ ERROR_INVALID_HANDLE, 0, EINVAL},
121
{ ERROR_WAIT_NO_CHILDREN, 0, ECHILD},
122
{ ERROR_CHILD_NOT_COMPLETE, 0, ECHILD},
123
{ ERROR_DIRECT_ACCESS_HANDLE, 0, EBADF},
124
{ ERROR_NEGATIVE_SEEK, 0, EINVAL},
125
{ ERROR_SEEK_ON_DEVICE, 0, EACCES},
126
{ ERROR_DIR_NOT_EMPTY, 0, ENOTEMPTY},
127
{ ERROR_NOT_LOCKED, 0, EACCES},
128
{ ERROR_BAD_PATHNAME, 0, ENOENT},
129
{ ERROR_MAX_THRDS_REACHED, 0, EAGAIN},
130
{ ERROR_LOCK_FAILED, 0, EACCES},
131
{ ERROR_ALREADY_EXISTS, 0, EEXIST},
132
{ ERROR_FILENAME_EXCED_RANGE, 0, ENOENT},
133
{ ERROR_NESTING_NOT_ALLOWED, 0, EAGAIN},
134
{ ERROR_NOT_ENOUGH_QUOTA, 0, ENOMEM},
135
{ ERROR_INVALID_STARTING_CODESEG,
136
ERROR_INFLOOP_IN_RELOC_CHAIN - ERROR_INVALID_STARTING_CODESEG,
138
{ ERROR_WRITE_PROTECT,
139
ERROR_SHARING_BUFFER_EXCEEDED - ERROR_WRITE_PROTECT,
141
{ WSAEINVAL, 0, EINVAL },
142
{ WSAEACCES, 0, EACCES },
143
{ WSAEBADF, 0, EBADF },
144
{ WSAEFAULT, 0, EFAULT },
145
{ WSAEINTR, 0, EINTR },
146
{ WSAEINVAL, 0, EINVAL },
147
{ WSAEMFILE, 0, EMFILE },
148
#ifdef WSANAMETOOLONG
149
{ WSANAMETOOLONG, 0, ENAMETOOLONG },
152
{ WSAENFILE, 0, ENFILE },
154
{ WSAENOTEMPTY, 0, ENOTEMPTY },
158
void netsysw32_win32_maperr(DWORD errcode)
162
for (i = 0; win_error_table[i].range >= 0; i++) {
163
if (errcode >= win_error_table[i].win_code &&
164
errcode <= win_error_table[i].win_code + win_error_table[i].range) {
165
errno = win_error_table[i].posix_code;
169
/* Not found: save original error code, negated so that we can
170
recognize it in unix_error_message */
174
/* Windows socket errors */
176
#define EWOULDBLOCK -WSAEWOULDBLOCK
177
#define EINPROGRESS -WSAEINPROGRESS
178
#define EALREADY -WSAEALREADY
179
#define ENOTSOCK -WSAENOTSOCK
180
#define EDESTADDRREQ -WSAEDESTADDRREQ
181
#define EMSGSIZE -WSAEMSGSIZE
182
#define EPROTOTYPE -WSAEPROTOTYPE
183
#define ENOPROTOOPT -WSAENOPROTOOPT
184
#define EPROTONOSUPPORT -WSAEPROTONOSUPPORT
185
#define ESOCKTNOSUPPORT -WSAESOCKTNOSUPPORT
186
#define EOPNOTSUPP -WSAEOPNOTSUPP
187
#define EPFNOSUPPORT -WSAEPFNOSUPPORT
188
#define EAFNOSUPPORT -WSAEAFNOSUPPORT
189
#define EADDRINUSE -WSAEADDRINUSE
190
#define EADDRNOTAVAIL -WSAEADDRNOTAVAIL
191
#define ENETDOWN -WSAENETDOWN
192
#define ENETUNREACH -WSAENETUNREACH
193
#define ENETRESET -WSAENETRESET
194
#define ECONNABORTED -WSAECONNABORTED
195
#define ECONNRESET -WSAECONNRESET
196
#define ENOBUFS -WSAENOBUFS
197
#define EISCONN -WSAEISCONN
198
#define ENOTCONN -WSAENOTCONN
199
#define ESHUTDOWN -WSAESHUTDOWN
200
#define ETOOMANYREFS -WSAETOOMANYREFS
201
#define ETIMEDOUT -WSAETIMEDOUT
202
#define ECONNREFUSED -WSAECONNREFUSED
203
#define ELOOP -WSAELOOP
204
#define EHOSTDOWN -WSAEHOSTDOWN
205
#define EHOSTUNREACH -WSAEHOSTUNREACH
206
#define EPROCLIM -WSAEPROCLIM
207
#define EUSERS -WSAEUSERS
208
#define EDQUOT -WSAEDQUOT
209
#define ESTALE -WSAESTALE
210
#define EREMOTE -WSAEREMOTE
212
#define EOVERFLOW -ERROR_ARITHMETIC_OVERFLOW
213
#define EACCESS EACCES
215
int netsysw32_error_table[] = {
216
E2BIG, EACCESS, EAGAIN, EBADF, EBUSY, ECHILD, EDEADLK, EDOM,
217
EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, EISDIR, EMFILE, EMLINK,
218
ENAMETOOLONG, ENFILE, ENODEV, ENOENT, ENOEXEC, ENOLCK, ENOMEM, ENOSPC,
219
ENOSYS, ENOTDIR, ENOTEMPTY, ENOTTY, ENXIO, EPERM, EPIPE, ERANGE,
220
EROFS, ESPIPE, ESRCH, EXDEV, EWOULDBLOCK, EINPROGRESS, EALREADY,
221
ENOTSOCK, EDESTADDRREQ, EMSGSIZE, EPROTOTYPE, ENOPROTOOPT,
222
EPROTONOSUPPORT, ESOCKTNOSUPPORT, EOPNOTSUPP, EPFNOSUPPORT,
223
EAFNOSUPPORT, EADDRINUSE, EADDRNOTAVAIL, ENETDOWN, ENETUNREACH,
224
ENETRESET, ECONNABORTED, ECONNRESET, ENOBUFS, EISCONN, ENOTCONN,
225
ESHUTDOWN, ETOOMANYREFS, ETIMEDOUT, ECONNREFUSED, EHOSTDOWN,
226
EHOSTUNREACH, ELOOP, EOVERFLOW /*, EUNKNOWNERR */
229
static value * unix_error_exn = NULL;
231
value netsysw32_unix_error_of_code (int errcode)
237
cst_to_constr(errcode, netsysw32_error_table, sizeof(netsysw32_error_table)/sizeof(int), -1);
238
if (errconstr == Val_int(-1)) {
239
err = alloc_small(1, 0);
240
Field(err, 0) = Val_int(errcode);
248
void netsysw32_unix_error(int errcode, char *cmdname, value cmdarg)
251
value name = Val_unit, err = Val_unit, arg = Val_unit;
253
Begin_roots3 (name, err, arg);
254
arg = cmdarg == Nothing ? copy_string("") : cmdarg;
255
name = copy_string(cmdname);
256
err = unix_error_of_code(errcode);
257
if (unix_error_exn == NULL) {
258
unix_error_exn = caml_named_value("Unix.Unix_error");
259
if (unix_error_exn == NULL)
260
invalid_argument("Exception Unix.Unix_error not initialized, please link unix.cma");
262
res = alloc_small(4, 0);
263
Field(res, 0) = *unix_error_exn;
265
Field(res, 2) = name;
271
void netsysw32_uerror(cmdname, cmdarg)
275
unix_error(errno, cmdname, cmdarg);