diff options
Diffstat (limited to 'src/os_win/os_errno.c')
-rw-r--r-- | src/os_win/os_errno.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/src/os_win/os_errno.c b/src/os_win/os_errno.c index ce50106b0cc..00ee638fbe3 100644 --- a/src/os_win/os_errno.c +++ b/src/os_win/os_errno.c @@ -1,4 +1,5 @@ /*- + * Copyright (c) 2014-2015 MongoDB, Inc. * Copyright (c) 2008-2014 WiredTiger, Inc. * All rights reserved. * @@ -7,6 +8,34 @@ #include "wt_internal.h" +static const int windows_error_offset = -29000; + +/* + * __wt_map_error_to_windows_error -- + * Return a negative integer, an encoded Windows error + * Standard C errors are positive integers from 0 - ~200 + * Windows errors are from 0 - 15999 according to the documentation + */ +static DWORD +__wt_map_error_to_windows_error(int error) { + /* Ensure we do not exceed the error range + Also validate he do not get any COM errors + (which are negative integers) + */ + WT_ASSERT(NULL, error > 0 && error > -(windows_error_offset)); + + return (error + -(windows_error_offset)); +} + +/* + * __wt_map_error_to_windows_error -- + * Return a positive integer, a decoded Windows error + */ +static int +__wt_map_windows_error_to_error(DWORD winerr) { + return (winerr + windows_error_offset); +} + /* * __wt_errno -- * Return errno, or WT_ERROR if errno not set. @@ -23,5 +52,73 @@ __wt_errno(void) /* GetLastError should only be called if we hit an actual error */ WT_ASSERT(NULL, err != ERROR_SUCCESS); - return (err == ERROR_SUCCESS ? WT_ERROR : err); + return (err == ERROR_SUCCESS ? + WT_ERROR : __wt_map_windows_error_to_error(err)); +} + +/* + * __wt_strerror -- + * Windows implementation of wiredtiger_strerror. + */ +const char * +__wt_strerror(int error) +{ + const char *p; + + /* + * POSIX errors are non-negative integers; check for 0 explicitly + * in-case the underlying strerror doesn't handle 0, some don't. + */ + if (error == 0) + return ("Successful return: 0"); + if (error > 0 && (p = strerror(error)) != NULL) + return (p); + return (NULL); +} + +/* + * __wt_strerror_r -- + * Windows implementation of wiredtiger_strerror_r. + */ +int +__wt_strerror_r(int error, char *buf, size_t buflen) +{ + DWORD lasterror; + const char *p; + + /* Require at least 2 bytes, printable character and trailing nul. */ + if (buflen < 2) + return (ENOMEM); + + /* + * Check for POSIX errors, Windows errors, then fallback to something + * generic. Copy the string into the user's buffer, return success if + * anything printed. + */ + p = __wt_strerror(error); + if (p != NULL && snprintf(buf, buflen, "%s", p) > 0) + return (0); + + if (error < 0) { + error = __wt_map_error_to_windows_error(error); + + lasterror = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error, + 0, /* let system choose the correct LANGID */ + buf, + buflen, + NULL); + + if (lasterror != 0) + return (0); + + /* Fall through to the fallback error code */ + } + + /* Fallback to a generic message, then guess it's a memory problem. */ + return ( + snprintf(buf, buflen, "error return: %d", error) > 0 ? 0 : ENOMEM); } |