1996-09-05 06:32:25 -07:00
|
|
|
/***********************************************************************/
|
|
|
|
/* */
|
|
|
|
/* Objective Caml */
|
|
|
|
/* */
|
|
|
|
/* Xavier Leroy, projet Cristal, INRIA Rocquencourt */
|
|
|
|
/* */
|
|
|
|
/* Copyright 1996 Institut National de Recherche en Informatique et */
|
1999-11-17 10:59:06 -08:00
|
|
|
/* en Automatique. All rights reserved. This file is distributed */
|
2001-12-07 05:41:02 -08:00
|
|
|
/* under the terms of the GNU Library General Public License, with */
|
|
|
|
/* the special exception on linking described in file ../../LICENSE. */
|
1996-09-05 06:32:25 -07:00
|
|
|
/* */
|
|
|
|
/***********************************************************************/
|
|
|
|
|
|
|
|
/* $Id$ */
|
|
|
|
|
2002-06-07 02:49:45 -07:00
|
|
|
#include <stddef.h>
|
1996-09-05 06:32:25 -07:00
|
|
|
#include <mlvalues.h>
|
1996-12-10 06:45:58 -08:00
|
|
|
#include <callback.h>
|
1996-09-05 06:32:25 -07:00
|
|
|
#include <alloc.h>
|
|
|
|
#include <memory.h>
|
|
|
|
#include <fail.h>
|
2001-07-24 02:05:25 -07:00
|
|
|
#include <custom.h>
|
1996-09-05 06:32:25 -07:00
|
|
|
#include "unixsupport.h"
|
|
|
|
#include "cst2constr.h"
|
|
|
|
#include <errno.h>
|
|
|
|
|
1997-09-03 07:38:02 -07:00
|
|
|
/* Heap-allocation of Windows file handles */
|
|
|
|
|
2001-07-24 02:05:25 -07:00
|
|
|
static int win_handle_compare(value v1, value v2)
|
|
|
|
{
|
|
|
|
HANDLE h1 = Handle_val(v1);
|
|
|
|
HANDLE h2 = Handle_val(v2);
|
|
|
|
return h1 == h2 ? 0 : h1 < h2 ? -1 : 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static long win_handle_hash(value v)
|
|
|
|
{
|
|
|
|
return (long) Handle_val(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct custom_operations win_handle_ops = {
|
|
|
|
"_handle",
|
|
|
|
custom_finalize_default,
|
|
|
|
win_handle_compare,
|
|
|
|
win_handle_hash,
|
|
|
|
custom_serialize_default,
|
|
|
|
custom_deserialize_default
|
|
|
|
};
|
|
|
|
|
1997-09-03 07:38:02 -07:00
|
|
|
value win_alloc_handle(HANDLE h)
|
|
|
|
{
|
2002-04-30 08:00:48 -07:00
|
|
|
value res = alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1);
|
1997-09-03 07:38:02 -07:00
|
|
|
Handle_val(res) = h;
|
2002-04-30 08:00:48 -07:00
|
|
|
Descr_kind_val(res) = KIND_HANDLE;
|
2003-01-06 06:52:57 -08:00
|
|
|
CRT_fd_val(res) = NO_CRT_FD;
|
2002-04-30 08:00:48 -07:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
value win_alloc_socket(SOCKET s)
|
|
|
|
{
|
|
|
|
value res = alloc_custom(&win_handle_ops, sizeof(struct filedescr), 0, 1);
|
|
|
|
Socket_val(res) = s;
|
|
|
|
Descr_kind_val(res) = KIND_SOCKET;
|
2004-04-01 05:12:36 -08:00
|
|
|
CRT_fd_val(res) = NO_CRT_FD;
|
2002-04-30 08:00:48 -07:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
value win_alloc_handle_or_socket(HANDLE h)
|
|
|
|
{
|
|
|
|
value res = win_alloc_handle(h);
|
|
|
|
int opt;
|
|
|
|
int optlen = sizeof(opt);
|
|
|
|
if (getsockopt((SOCKET) h, SOL_SOCKET, SO_TYPE, (char *)&opt, &optlen) == 0)
|
|
|
|
Descr_kind_val(res) = KIND_SOCKET;
|
1997-09-03 07:38:02 -07:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2001-08-28 07:47:48 -07:00
|
|
|
/* Mapping of Windows error codes to POSIX error codes */
|
|
|
|
|
|
|
|
struct error_entry { unsigned long win_code; int range; int posix_code; };
|
|
|
|
|
|
|
|
static struct error_entry win_error_table[] = {
|
|
|
|
{ ERROR_INVALID_FUNCTION, 0, EINVAL},
|
|
|
|
{ ERROR_FILE_NOT_FOUND, 0, ENOENT},
|
|
|
|
{ ERROR_PATH_NOT_FOUND, 0, ENOENT},
|
|
|
|
{ ERROR_TOO_MANY_OPEN_FILES, 0, EMFILE},
|
|
|
|
{ ERROR_ACCESS_DENIED, 0, EACCES},
|
|
|
|
{ ERROR_INVALID_HANDLE, 0, EBADF},
|
|
|
|
{ ERROR_ARENA_TRASHED, 0, ENOMEM},
|
|
|
|
{ ERROR_NOT_ENOUGH_MEMORY, 0, ENOMEM},
|
|
|
|
{ ERROR_INVALID_BLOCK, 0, ENOMEM},
|
|
|
|
{ ERROR_BAD_ENVIRONMENT, 0, E2BIG},
|
|
|
|
{ ERROR_BAD_FORMAT, 0, ENOEXEC},
|
|
|
|
{ ERROR_INVALID_ACCESS, 0, EINVAL},
|
|
|
|
{ ERROR_INVALID_DATA, 0, EINVAL},
|
|
|
|
{ ERROR_INVALID_DRIVE, 0, ENOENT},
|
|
|
|
{ ERROR_CURRENT_DIRECTORY, 0, EACCES},
|
|
|
|
{ ERROR_NOT_SAME_DEVICE, 0, EXDEV},
|
|
|
|
{ ERROR_NO_MORE_FILES, 0, ENOENT},
|
|
|
|
{ ERROR_LOCK_VIOLATION, 0, EACCES},
|
|
|
|
{ ERROR_BAD_NETPATH, 0, ENOENT},
|
|
|
|
{ ERROR_NETWORK_ACCESS_DENIED, 0, EACCES},
|
|
|
|
{ ERROR_BAD_NET_NAME, 0, ENOENT},
|
|
|
|
{ ERROR_FILE_EXISTS, 0, EEXIST},
|
|
|
|
{ ERROR_CANNOT_MAKE, 0, EACCES},
|
|
|
|
{ ERROR_FAIL_I24, 0, EACCES},
|
|
|
|
{ ERROR_INVALID_PARAMETER, 0, EINVAL},
|
|
|
|
{ ERROR_NO_PROC_SLOTS, 0, EAGAIN},
|
|
|
|
{ ERROR_DRIVE_LOCKED, 0, EACCES},
|
|
|
|
{ ERROR_BROKEN_PIPE, 0, EPIPE},
|
|
|
|
{ ERROR_DISK_FULL, 0, ENOSPC},
|
|
|
|
{ ERROR_INVALID_TARGET_HANDLE, 0, EBADF},
|
|
|
|
{ ERROR_INVALID_HANDLE, 0, EINVAL},
|
|
|
|
{ ERROR_WAIT_NO_CHILDREN, 0, ECHILD},
|
|
|
|
{ ERROR_CHILD_NOT_COMPLETE, 0, ECHILD},
|
|
|
|
{ ERROR_DIRECT_ACCESS_HANDLE, 0, EBADF},
|
|
|
|
{ ERROR_NEGATIVE_SEEK, 0, EINVAL},
|
|
|
|
{ ERROR_SEEK_ON_DEVICE, 0, EACCES},
|
|
|
|
{ ERROR_DIR_NOT_EMPTY, 0, ENOTEMPTY},
|
|
|
|
{ ERROR_NOT_LOCKED, 0, EACCES},
|
|
|
|
{ ERROR_BAD_PATHNAME, 0, ENOENT},
|
|
|
|
{ ERROR_MAX_THRDS_REACHED, 0, EAGAIN},
|
|
|
|
{ ERROR_LOCK_FAILED, 0, EACCES},
|
|
|
|
{ ERROR_ALREADY_EXISTS, 0, EEXIST},
|
|
|
|
{ ERROR_FILENAME_EXCED_RANGE, 0, ENOENT},
|
|
|
|
{ ERROR_NESTING_NOT_ALLOWED, 0, EAGAIN},
|
|
|
|
{ ERROR_NOT_ENOUGH_QUOTA, 0, ENOMEM},
|
|
|
|
{ ERROR_INVALID_STARTING_CODESEG,
|
|
|
|
ERROR_INFLOOP_IN_RELOC_CHAIN - ERROR_INVALID_STARTING_CODESEG,
|
|
|
|
ENOEXEC },
|
|
|
|
{ ERROR_WRITE_PROTECT,
|
|
|
|
ERROR_SHARING_BUFFER_EXCEEDED - ERROR_WRITE_PROTECT,
|
|
|
|
EACCES },
|
2001-11-27 06:05:29 -08:00
|
|
|
{ WSAEINVAL, 0, EINVAL },
|
2001-12-03 02:27:29 -08:00
|
|
|
{ WSAEACCES, 0, EACCES },
|
|
|
|
{ WSAEBADF, 0, EBADF },
|
|
|
|
{ WSAEFAULT, 0, EFAULT },
|
|
|
|
{ WSAEINTR, 0, EINTR },
|
|
|
|
{ WSAEINVAL, 0, EINVAL },
|
|
|
|
{ WSAEMFILE, 0, EMFILE },
|
2001-12-03 02:51:35 -08:00
|
|
|
#ifdef WSANAMETOOLONG
|
2001-12-03 02:27:29 -08:00
|
|
|
{ WSANAMETOOLONG, 0, ENAMETOOLONG },
|
2001-12-03 02:51:35 -08:00
|
|
|
#endif
|
|
|
|
#ifdef WSAENFILE
|
2001-12-03 02:27:29 -08:00
|
|
|
{ WSAENFILE, 0, ENFILE },
|
2001-12-03 02:51:35 -08:00
|
|
|
#endif
|
2001-12-03 02:27:29 -08:00
|
|
|
{ WSAENOTEMPTY, 0, ENOTEMPTY },
|
2001-08-28 07:47:48 -07:00
|
|
|
{ 0, -1, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
void win32_maperr(unsigned long errcode)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; win_error_table[i].range >= 0; i++) {
|
|
|
|
if (errcode >= win_error_table[i].win_code &&
|
|
|
|
errcode <= win_error_table[i].win_code + win_error_table[i].range) {
|
|
|
|
errno = win_error_table[i].posix_code;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Not found: save original error code, negated so that we can
|
|
|
|
recognize it in unix_error_message */
|
|
|
|
errno = -errcode;
|
|
|
|
}
|
|
|
|
|
1996-09-05 06:32:25 -07:00
|
|
|
/* Windows socket errors */
|
|
|
|
|
2001-08-28 07:47:48 -07:00
|
|
|
#define EWOULDBLOCK -WSAEWOULDBLOCK
|
|
|
|
#define EINPROGRESS -WSAEINPROGRESS
|
|
|
|
#define EALREADY -WSAEALREADY
|
|
|
|
#define ENOTSOCK -WSAENOTSOCK
|
|
|
|
#define EDESTADDRREQ -WSAEDESTADDRREQ
|
|
|
|
#define EMSGSIZE -WSAEMSGSIZE
|
|
|
|
#define EPROTOTYPE -WSAEPROTOTYPE
|
|
|
|
#define ENOPROTOOPT -WSAENOPROTOOPT
|
|
|
|
#define EPROTONOSUPPORT -WSAEPROTONOSUPPORT
|
|
|
|
#define ESOCKTNOSUPPORT -WSAESOCKTNOSUPPORT
|
|
|
|
#define EOPNOTSUPP -WSAEOPNOTSUPP
|
|
|
|
#define EPFNOSUPPORT -WSAEPFNOSUPPORT
|
|
|
|
#define EAFNOSUPPORT -WSAEAFNOSUPPORT
|
|
|
|
#define EADDRINUSE -WSAEADDRINUSE
|
|
|
|
#define EADDRNOTAVAIL -WSAEADDRNOTAVAIL
|
|
|
|
#define ENETDOWN -WSAENETDOWN
|
|
|
|
#define ENETUNREACH -WSAENETUNREACH
|
|
|
|
#define ENETRESET -WSAENETRESET
|
|
|
|
#define ECONNABORTED -WSAECONNABORTED
|
|
|
|
#define ECONNRESET -WSAECONNRESET
|
|
|
|
#define ENOBUFS -WSAENOBUFS
|
|
|
|
#define EISCONN -WSAEISCONN
|
|
|
|
#define ENOTCONN -WSAENOTCONN
|
|
|
|
#define ESHUTDOWN -WSAESHUTDOWN
|
|
|
|
#define ETOOMANYREFS -WSAETOOMANYREFS
|
|
|
|
#define ETIMEDOUT -WSAETIMEDOUT
|
|
|
|
#define ECONNREFUSED -WSAECONNREFUSED
|
|
|
|
#define ELOOP -WSAELOOP
|
|
|
|
#define EHOSTDOWN -WSAEHOSTDOWN
|
|
|
|
#define EHOSTUNREACH -WSAEHOSTUNREACH
|
|
|
|
#define EPROCLIM -WSAEPROCLIM
|
|
|
|
#define EUSERS -WSAEUSERS
|
|
|
|
#define EDQUOT -WSAEDQUOT
|
|
|
|
#define ESTALE -WSAESTALE
|
|
|
|
#define EREMOTE -WSAEREMOTE
|
|
|
|
|
2002-03-06 08:55:20 -08:00
|
|
|
#define EOVERFLOW -ERROR_ARITHMETIC_OVERFLOW
|
2001-08-28 07:47:48 -07:00
|
|
|
#define EACCESS EACCES
|
1996-09-05 06:32:25 -07:00
|
|
|
|
|
|
|
int error_table[] = {
|
|
|
|
E2BIG, EACCESS, EAGAIN, EBADF, EBUSY, ECHILD, EDEADLK, EDOM,
|
|
|
|
EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, EISDIR, EMFILE, EMLINK,
|
|
|
|
ENAMETOOLONG, ENFILE, ENODEV, ENOENT, ENOEXEC, ENOLCK, ENOMEM, ENOSPC,
|
|
|
|
ENOSYS, ENOTDIR, ENOTEMPTY, ENOTTY, ENXIO, EPERM, EPIPE, ERANGE,
|
|
|
|
EROFS, ESPIPE, ESRCH, EXDEV, EWOULDBLOCK, EINPROGRESS, EALREADY,
|
|
|
|
ENOTSOCK, EDESTADDRREQ, EMSGSIZE, EPROTOTYPE, ENOPROTOOPT,
|
|
|
|
EPROTONOSUPPORT, ESOCKTNOSUPPORT, EOPNOTSUPP, EPFNOSUPPORT,
|
|
|
|
EAFNOSUPPORT, EADDRINUSE, EADDRNOTAVAIL, ENETDOWN, ENETUNREACH,
|
|
|
|
ENETRESET, ECONNABORTED, ECONNRESET, ENOBUFS, EISCONN, ENOTCONN,
|
|
|
|
ESHUTDOWN, ETOOMANYREFS, ETIMEDOUT, ECONNREFUSED, EHOSTDOWN,
|
2002-03-06 08:55:20 -08:00
|
|
|
EHOSTUNREACH, ELOOP, EOVERFLOW /*, EUNKNOWNERR */
|
1996-09-05 06:32:25 -07:00
|
|
|
};
|
|
|
|
|
1996-11-08 06:47:07 -08:00
|
|
|
static value * unix_error_exn = NULL;
|
1996-09-05 06:32:25 -07:00
|
|
|
|
1998-08-19 06:11:47 -07:00
|
|
|
void unix_error(int errcode, char *cmdname, value cmdarg)
|
1996-09-05 06:32:25 -07:00
|
|
|
{
|
|
|
|
value res;
|
1998-08-19 06:11:47 -07:00
|
|
|
value name = Val_unit, err = Val_unit, arg = Val_unit;
|
|
|
|
int errconstr;
|
1997-05-26 10:16:31 -07:00
|
|
|
|
1998-08-19 06:11:47 -07:00
|
|
|
Begin_roots3 (name, err, arg);
|
|
|
|
arg = cmdarg == Nothing ? copy_string("") : cmdarg;
|
|
|
|
name = copy_string(cmdname);
|
|
|
|
errconstr =
|
|
|
|
cst_to_constr(errcode, error_table, sizeof(error_table)/sizeof(int), -1);
|
|
|
|
if (errconstr == Val_int(-1)) {
|
1998-10-26 11:19:32 -08:00
|
|
|
err = alloc_small(1, 0);
|
1998-08-19 06:11:47 -07:00
|
|
|
Field(err, 0) = Val_int(errcode);
|
|
|
|
} else {
|
|
|
|
err = errconstr;
|
|
|
|
}
|
1997-05-26 10:16:31 -07:00
|
|
|
if (unix_error_exn == NULL) {
|
|
|
|
unix_error_exn = caml_named_value("Unix.Unix_error");
|
|
|
|
if (unix_error_exn == NULL)
|
1998-08-19 06:11:47 -07:00
|
|
|
invalid_argument("Exception Unix.Unix_error not initialized, please link unix.cma");
|
1997-05-26 10:16:31 -07:00
|
|
|
}
|
1998-10-26 11:19:32 -08:00
|
|
|
res = alloc_small(4, 0);
|
1997-05-26 10:16:31 -07:00
|
|
|
Field(res, 0) = *unix_error_exn;
|
1998-08-19 06:11:47 -07:00
|
|
|
Field(res, 1) = err;
|
1997-05-26 10:16:31 -07:00
|
|
|
Field(res, 2) = name;
|
|
|
|
Field(res, 3) = arg;
|
|
|
|
End_roots();
|
1996-09-05 06:32:25 -07:00
|
|
|
mlraise(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
void uerror(cmdname, cmdarg)
|
|
|
|
char * cmdname;
|
|
|
|
value cmdarg;
|
|
|
|
{
|
|
|
|
unix_error(errno, cmdname, cmdarg);
|
|
|
|
}
|