diff options
Diffstat (limited to 'src/os_win/os_winerr.c')
| -rw-r--r-- | src/os_win/os_winerr.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/os_win/os_winerr.c b/src/os_win/os_winerr.c new file mode 100644 index 00000000000..70499580c48 --- /dev/null +++ b/src/os_win/os_winerr.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 2014-2016 MongoDB, Inc. + * Copyright (c) 2008-2014 WiredTiger, Inc. + * All rights reserved. + * + * See the file LICENSE for redistribution information. + */ + +#include "wt_internal.h" + +/* + * __wt_getlasterror -- + * Return GetLastError, or a relatively generic Windows error if the system + * error code isn't set. + */ +DWORD +__wt_getlasterror(void) +{ + DWORD windows_error; + + /* + * Check for ERROR_SUCCESS: + * It's easy to introduce a problem by calling the wrong error function, + * for example, this function when the MSVC function set the C runtime + * error value. Handle gracefully and always return an error. + */ + windows_error = GetLastError(); + return (windows_error == ERROR_SUCCESS ? + ERROR_INVALID_PARAMETER : windows_error); +} + +/* + * __wt_map_windows_error -- + * Map Windows errors to POSIX/ANSI errors. + */ +int +__wt_map_windows_error(DWORD windows_error) +{ + static const struct { + int windows_error; + int posix_error; + } list[] = { + { ERROR_ACCESS_DENIED, EACCES }, + { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_ARENA_TRASHED, EFAULT }, + { ERROR_BAD_COMMAND, EFAULT }, + { ERROR_BAD_ENVIRONMENT, EFAULT }, + { ERROR_BAD_FORMAT, EFAULT }, + { ERROR_BAD_NETPATH, ENOENT }, + { ERROR_BAD_NET_NAME, ENOENT }, + { ERROR_BAD_PATHNAME, ENOENT }, + { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_CANNOT_MAKE, EACCES }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, + { ERROR_CURRENT_DIRECTORY, EACCES }, + { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, + { ERROR_DISK_FULL, ENOSPC }, + { ERROR_DRIVE_LOCKED, EACCES }, + { ERROR_FAIL_I24, EACCES }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, + { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_GEN_FAILURE, EFAULT }, + { ERROR_INVALID_ACCESS, EACCES }, + { ERROR_INVALID_BLOCK, EFAULT }, + { ERROR_INVALID_DATA, EFAULT }, + { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_INVALID_FUNCTION, EINVAL }, + { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_INVALID_PARAMETER, EINVAL }, + { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_LOCK_FAILED, EBUSY }, + { ERROR_LOCK_VIOLATION, EBUSY }, + { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_NEGATIVE_SEEK, EINVAL }, + { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM }, + { ERROR_NOT_LOCKED, EACCES }, + { ERROR_NOT_READY, EBUSY }, + { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_DATA, EPIPE }, + { ERROR_NO_MORE_FILES, EMFILE }, + { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_PATH_NOT_FOUND, ENOENT }, + { ERROR_READ_FAULT, EFAULT }, + { ERROR_RETRY, EINTR }, + { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_SHARING_VIOLATION, EBUSY }, + { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_WRITE_FAULT, EFAULT }, + { ERROR_WRITE_PROTECT, EACCES }, + }; + int i; + + for (i = 0; i < WT_ELEMENTS(list); ++i) + if (windows_error == list[i].windows_error) + return (list[i].posix_error); + + /* Untranslatable error, go generic. */ + return (WT_ERROR); +} + +/* + * __wt_formatmessage -- + * Windows error formatting. + */ +const char * +__wt_formatmessage(WT_SESSION_IMPL *session, DWORD windows_error) +{ + /* + * !!! + * This function MUST handle a NULL session handle. + * + * Grow the session error buffer as necessary. + */ + if (session != NULL && + __wt_buf_initsize(session, &session->err, 512) == 0 && + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, windows_error, + 0, /* Let system choose the correct LANGID. */ + session->err.mem, (DWORD)512, NULL) != 0) + return (session->err.data); + + return ("Unable to format Windows error string"); +} |
