/* * error.c: Error reporting * * Author: * Dick Porter (dick@ximian.com) * * (C) 2002 Ximian, Inc. */ #include #include #include #include #include #include "mono/io-layer/wapi.h" #include "mono/io-layer/wapi-private.h" #include "mono/utils/mono-once.h" static pthread_key_t error_key; static mono_once_t error_key_once=MONO_ONCE_INIT; static void error_init(void) { int ret; ret = pthread_key_create(&error_key, NULL); g_assert (ret == 0); } void _wapi_error_cleanup (void) { int ret; ret = pthread_key_delete (error_key); g_assert (ret == 0); } /** * GetLastError: * * Retrieves the last error that occurred in the calling thread. * * Return value: The error code for the last error that happened on * the calling thread. */ guint32 GetLastError(void) { guint32 err; void *errptr; if (_wapi_has_shut_down) return 0; mono_once(&error_key_once, error_init); errptr=pthread_getspecific(error_key); err=GPOINTER_TO_UINT(errptr); return(err); } /** * SetLastError: * @code: The error code. * * Sets the error code in the calling thread. */ void SetLastError(guint32 code) { int ret; if (_wapi_has_shut_down) return; /* Set the thread-local error code */ mono_once(&error_key_once, error_init); ret = pthread_setspecific(error_key, GUINT_TO_POINTER(code)); g_assert (ret == 0); } guint32 errno_to_WSA (guint32 code, const gchar *function_name) { gint result = -1; char *sys_error; gchar *msg; switch (code) { case 0: result = ERROR_SUCCESS; break; case EACCES: result = WSAEACCES; break; #ifdef EADDRINUSE case EADDRINUSE: result = WSAEADDRINUSE; break; #endif #ifdef EAFNOSUPPORT case EAFNOSUPPORT: result = WSAEAFNOSUPPORT; break; #endif #if EAGAIN != EWOULDBLOCK case EAGAIN: result = WSAEWOULDBLOCK; break; #endif #ifdef EALREADY case EALREADY: result = WSAEALREADY; break; #endif case EBADF: result = WSAENOTSOCK; break; #ifdef ECONNABORTED case ECONNABORTED: result = WSAENETDOWN; break; #endif #ifdef ECONNREFUSED case ECONNREFUSED: result = WSAECONNREFUSED; break; #endif #ifdef ECONNRESET case ECONNRESET: result = WSAECONNRESET; break; #endif case EFAULT: result = WSAEFAULT; break; #ifdef EHOSTUNREACH case EHOSTUNREACH: result = WSAEHOSTUNREACH; break; #endif #ifdef EINPROGRESS case EINPROGRESS: result = WSAEINPROGRESS; break; #endif case EINTR: result = WSAEINTR; break; case EINVAL: result = WSAEINVAL; break; /*FIXME: case EIO: result = WSAE????; break; */ #ifdef EISCONN case EISCONN: result = WSAEISCONN; break; #endif /* FIXME: case ELOOP: result = WSA????; break; */ case EMFILE: result = WSAEMFILE; break; #ifdef EMSGSIZE case EMSGSIZE: result = WSAEMSGSIZE; break; #endif /* FIXME: case ENAMETOOLONG: result = WSAEACCES; break; */ #ifdef ENETUNREACH case ENETUNREACH: result = WSAENETUNREACH; break; #endif #ifdef ENOBUFS case ENOBUFS: result = WSAENOBUFS; break; /* not documented */ #endif /* case ENOENT: result = WSAE????; break; */ case ENOMEM: result = WSAENOBUFS; break; #ifdef ENOPROTOOPT case ENOPROTOOPT: result = WSAENOPROTOOPT; break; #endif #ifdef ENOSR case ENOSR: result = WSAENETDOWN; break; #endif #ifdef ENOTCONN case ENOTCONN: result = WSAENOTCONN; break; #endif /*FIXME: case ENOTDIR: result = WSAE????; break; */ #ifdef ENOTSOCK case ENOTSOCK: result = WSAENOTSOCK; break; #endif case ENOTTY: result = WSAENOTSOCK; break; #ifdef EOPNOTSUPP case EOPNOTSUPP: result = WSAEOPNOTSUPP; break; #endif case EPERM: result = WSAEACCES; break; case EPIPE: result = WSAESHUTDOWN; break; #ifdef EPROTONOSUPPORT case EPROTONOSUPPORT: result = WSAEPROTONOSUPPORT; break; #endif #if ERESTARTSYS case ERESTARTSYS: result = WSAENETDOWN; break; #endif /*FIXME: case EROFS: result = WSAE????; break; */ #ifdef ESOCKTNOSUPPORT case ESOCKTNOSUPPORT: result = WSAESOCKTNOSUPPORT; break; #endif #ifdef ETIMEDOUT case ETIMEDOUT: result = WSAETIMEDOUT; break; #endif #ifdef EWOULDBLOCK case EWOULDBLOCK: result = WSAEWOULDBLOCK; break; #endif #ifdef EADDRNOTAVAIL case EADDRNOTAVAIL: result = WSAEADDRNOTAVAIL; break; #endif /* This might happen with unix sockets */ case ENOENT: result = WSAECONNREFUSED; break; #ifdef EDESTADDRREQ case EDESTADDRREQ: result = WSAEDESTADDRREQ; break; #endif #ifdef EHOSTDOWN case EHOSTDOWN: result = WSAEHOSTDOWN; break; #endif #ifdef ENETDOWN case ENETDOWN: result = WSAENETDOWN; break; #endif case ENODEV: result = WSAENETDOWN; break; default: sys_error = strerror (code); msg = g_locale_to_utf8 (sys_error, strlen (sys_error), NULL, NULL, NULL); if (function_name == NULL) function_name = __func__; g_warning ("%s: Need to translate %d [%s] into winsock error", function_name, code, msg); g_free (msg); result = WSASYSCALLFAILURE; } return result; } gint _wapi_get_win32_file_error (gint err) { gint ret; /* mapping ideas borrowed from wine. they may need some work */ switch (err) { case EACCES: case EPERM: case EROFS: ret = ERROR_ACCESS_DENIED; break; case EAGAIN: ret = ERROR_SHARING_VIOLATION; break; case EBUSY: ret = ERROR_LOCK_VIOLATION; break; case EEXIST: ret = ERROR_FILE_EXISTS; break; case EINVAL: case ESPIPE: ret = ERROR_SEEK; break; case EISDIR: ret = ERROR_CANNOT_MAKE; break; case ENFILE: case EMFILE: ret = ERROR_TOO_MANY_OPEN_FILES; break; case ENOENT: case ENOTDIR: ret = ERROR_FILE_NOT_FOUND; break; case ENOSPC: ret = ERROR_HANDLE_DISK_FULL; break; case ENOTEMPTY: ret = ERROR_DIR_NOT_EMPTY; break; case ENOEXEC: ret = ERROR_BAD_FORMAT; break; case ENAMETOOLONG: ret = ERROR_FILENAME_EXCED_RANGE; break; #ifdef EINPROGRESS case EINPROGRESS: ret = ERROR_IO_PENDING; break; #endif case ENOSYS: ret = ERROR_NOT_SUPPORTED; break; case EBADF: ret = ERROR_INVALID_HANDLE; break; case EIO: ret = ERROR_INVALID_HANDLE; break; case EINTR: ret = ERROR_IO_PENDING; /* best match I could find */ break; case EPIPE: ret = ERROR_WRITE_FAULT; break; default: g_message ("Unknown errno: %s\n", g_strerror (err)); ret = ERROR_GEN_FAILURE; break; } return ret; }