Files
2017-09-04 13:40:25 -05:00

428 lines
7.7 KiB
C

/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999,2008 Oracle. All rights reserved.
*
* $Id: os_errno.c 63573 2008-05-23 21:43:21Z trent.nelson $
*/
#include "db_config.h"
#include "db_int.h"
/*
* __os_get_errno_ret_zero --
* Return the last system error, including an error of zero.
*/
int
__os_get_errno_ret_zero()
{
/* This routine must be able to return the same value repeatedly. */
return (errno);
}
/*
* We've seen cases where system calls failed but errno was never set. For
* that reason, __os_get_errno() and __os_get_syserr set errno to EAGAIN if
* it's not already set, to work around the problem. For obvious reasons,
* we can only call this function if we know an error has occurred, that
* is, we can't test the return for a non-zero value after the get call.
*
* __os_get_errno --
* Return the last ANSI C "errno" value or EAGAIN if the last error
* is zero.
*/
int
__os_get_errno()
{
/* This routine must be able to return the same value repeatedly. */
if (errno == 0)
__os_set_errno(EAGAIN);
return (errno);
}
#ifdef HAVE_REPLICATION_THREADS
/*
* __os_get_neterr --
* Return the last networking error or EAGAIN if the last error is zero.
*
* PUBLIC: #ifdef HAVE_REPLICATION_THREADS
* PUBLIC: int __os_get_neterr __P((void));
* PUBLIC: #endif
*/
int
__os_get_neterr()
{
int err;
/* This routine must be able to return the same value repeatedly. */
err = WSAGetLastError();
if (err == 0)
WSASetLastError(err = ERROR_RETRY);
return (err);
}
#endif
/*
* __os_get_syserr --
* Return the last system error or EAGAIN if the last error is zero.
*/
int
__os_get_syserr()
{
int err;
/* This routine must be able to return the same value repeatedly. */
err = GetLastError();
if (err == 0)
SetLastError(err = ERROR_RETRY);
return (err);
}
/*
* __os_set_errno --
* Set the value of errno.
*/
void
__os_set_errno(evalue)
int evalue;
{
/*
* This routine is called by the compatibility interfaces (DB 1.85,
* dbm and hsearch). Force values > 0, that is, not one of DB 2.X
* and later's public error returns. If something bad has happened,
* default to EFAULT -- a nasty return. Otherwise, default to EINVAL.
* As the compatibility APIs aren't included on Windows, the Windows
* version of this routine doesn't need this behavior.
*/
errno =
evalue >= 0 ? evalue : (evalue == DB_RUNRECOVERY ? EFAULT : EINVAL);
}
/*
* __os_strerror --
* Return a string associated with the system error.
*/
char *
__os_strerror(error, buf, len)
int error;
char *buf;
size_t len;
{
#ifdef DB_WINCE
#define MAX_TMPBUF_LEN 512
_TCHAR tbuf[MAX_TMPBUF_LEN];
size_t maxlen;
DB_ASSERT(NULL, error != 0);
memset(tbuf, 0, sizeof(_TCHAR)*MAX_TMPBUF_LEN);
maxlen = (len > MAX_TMPBUF_LEN ? MAX_TMPBUF_LEN : len);
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, (DWORD)error,
0, tbuf, maxlen-1, NULL);
if (WideCharToMultiByte(CP_UTF8, 0, tbuf, -1,
buf, len, 0, NULL) == 0)
strncpy(buf, "Error message translation failed.", len);
#else
DB_ASSERT(NULL, error != 0);
/*
* Explicitly call FormatMessageA, since we want to receive a char
* string back, not a tchar string.
*/
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM,
0, (DWORD)error, 0, buf, (DWORD)(len - 1), NULL);
buf[len - 1] = '\0';
#endif
return (buf);
}
/*
* __os_posix_err --
* Convert a system error to a POSIX error.
*/
int
__os_posix_err(error)
int error;
{
/* Handle calls on successful returns. */
if (error == 0)
return (0);
/*
* Translate the Windows error codes we care about.
*/
switch (error) {
case ERROR_INVALID_PARAMETER:
return (EINVAL);
case ERROR_FILE_NOT_FOUND:
case ERROR_INVALID_DRIVE:
case ERROR_PATH_NOT_FOUND:
return (ENOENT);
case ERROR_NO_MORE_FILES:
case ERROR_TOO_MANY_OPEN_FILES:
return (EMFILE);
case ERROR_ACCESS_DENIED:
return (EPERM);
case ERROR_INVALID_HANDLE:
return (EBADF);
case ERROR_NOT_ENOUGH_MEMORY:
return (ENOMEM);
case ERROR_DISK_FULL:
return (ENOSPC);
case ERROR_ARENA_TRASHED:
case ERROR_BAD_COMMAND:
case ERROR_BAD_ENVIRONMENT:
case ERROR_BAD_FORMAT:
case ERROR_GEN_FAILURE:
case ERROR_INVALID_ACCESS:
case ERROR_INVALID_BLOCK:
case ERROR_INVALID_DATA:
case ERROR_READ_FAULT:
case ERROR_WRITE_FAULT:
return (EFAULT);
case ERROR_ALREADY_EXISTS:
case ERROR_FILE_EXISTS:
return (EEXIST);
case ERROR_NOT_SAME_DEVICE:
return (EXDEV);
case ERROR_WRITE_PROTECT:
return (EACCES);
case ERROR_LOCK_FAILED:
case ERROR_LOCK_VIOLATION:
case ERROR_NOT_READY:
case ERROR_SHARING_VIOLATION:
return (EBUSY);
case ERROR_RETRY:
return (EINTR);
}
/*
* Translate the Windows socket error codes.
*/
switch (error) {
case WSAEADDRINUSE:
#ifdef EADDRINUSE
return (EADDRINUSE);
#else
break;
#endif
case WSAEADDRNOTAVAIL:
#ifdef EADDRNOTAVAIL
return (EADDRNOTAVAIL);
#else
break;
#endif
case WSAEAFNOSUPPORT:
#ifdef EAFNOSUPPORT
return (EAFNOSUPPORT);
#else
break;
#endif
case WSAEALREADY:
#ifdef EALREADY
return (EALREADY);
#else
break;
#endif
case WSAEBADF:
return (EBADF);
case WSAECONNABORTED:
#ifdef ECONNABORTED
return (ECONNABORTED);
#else
break;
#endif
case WSAECONNREFUSED:
#ifdef ECONNREFUSED
return (ECONNREFUSED);
#else
break;
#endif
case WSAECONNRESET:
#ifdef ECONNRESET
return (ECONNRESET);
#else
break;
#endif
case WSAEDESTADDRREQ:
#ifdef EDESTADDRREQ
return (EDESTADDRREQ);
#else
break;
#endif
case WSAEFAULT:
return (EFAULT);
case WSAEHOSTDOWN:
#ifdef EHOSTDOWN
return (EHOSTDOWN);
#else
break;
#endif
case WSAEHOSTUNREACH:
#ifdef EHOSTUNREACH
return (EHOSTUNREACH);
#else
break;
#endif
case WSAEINPROGRESS:
#ifdef EINPROGRESS
return (EINPROGRESS);
#else
break;
#endif
case WSAEINTR:
return (EINTR);
case WSAEINVAL:
return (EINVAL);
case WSAEISCONN:
#ifdef EISCONN
return (EISCONN);
#else
break;
#endif
case WSAELOOP:
#ifdef ELOOP
return (ELOOP);
#else
break;
#endif
case WSAEMFILE:
return (EMFILE);
case WSAEMSGSIZE:
#ifdef EMSGSIZE
return (EMSGSIZE);
#else
break;
#endif
case WSAENAMETOOLONG:
return (ENAMETOOLONG);
case WSAENETDOWN:
#ifdef ENETDOWN
return (ENETDOWN);
#else
break;
#endif
case WSAENETRESET:
#ifdef ENETRESET
return (ENETRESET);
#else
break;
#endif
case WSAENETUNREACH:
#ifdef ENETUNREACH
return (ENETUNREACH);
#else
break;
#endif
case WSAENOBUFS:
#ifdef ENOBUFS
return (ENOBUFS);
#else
break;
#endif
case WSAENOPROTOOPT:
#ifdef ENOPROTOOPT
return (ENOPROTOOPT);
#else
break;
#endif
case WSAENOTCONN:
#ifdef ENOTCONN
return (ENOTCONN);
#else
break;
#endif
case WSANOTINITIALISED:
return (EAGAIN);
case WSAENOTSOCK:
#ifdef ENOTSOCK
return (ENOTSOCK);
#else
break;
#endif
case WSAEOPNOTSUPP:
return (DB_OPNOTSUP);
case WSAEPFNOSUPPORT:
#ifdef EPFNOSUPPORT
return (EPFNOSUPPORT);
#else
break;
#endif
case WSAEPROTONOSUPPORT:
#ifdef EPROTONOSUPPORT
return (EPROTONOSUPPORT);
#else
break;
#endif
case WSAEPROTOTYPE:
#ifdef EPROTOTYPE
return (EPROTOTYPE);
#else
break;
#endif
case WSAESHUTDOWN:
#ifdef ESHUTDOWN
return (ESHUTDOWN);
#else
break;
#endif
case WSAESOCKTNOSUPPORT:
#ifdef ESOCKTNOSUPPORT
return (ESOCKTNOSUPPORT);
#else
break;
#endif
case WSAETIMEDOUT:
#ifdef ETIMEDOUT
return (ETIMEDOUT);
#else
break;
#endif
case WSAETOOMANYREFS:
#ifdef ETOOMANYREFS
return (ETOOMANYREFS);
#else
break;
#endif
case WSAEWOULDBLOCK:
#ifdef EWOULDBLOCK
return (EWOULDBLOCK);
#else
return (EAGAIN);
#endif
case WSAHOST_NOT_FOUND:
#ifdef EHOSTUNREACH
return (EHOSTUNREACH);
#else
break;
#endif
case WSASYSNOTREADY:
return (EAGAIN);
case WSATRY_AGAIN:
return (EAGAIN);
case WSAVERNOTSUPPORTED:
return (DB_OPNOTSUP);
case WSAEACCES:
return (EACCES);
}
/*
* EFAULT is the default if we don't have a translation.
*/
return (EFAULT);
}