Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions cpp/src/arrow/io/file_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1150,5 +1150,48 @@ TEST_F(TestStdio, ReadStdinReadAfterClose) {
ASSERT_EQ(sizeof(buffer), input.Tell());
}

#ifdef _WIN32
// Test Windows error code mapping in mman.h
// Note: We include mman.h here to test the __map_mman_error function directly
#include "arrow/io/mman.h"

TEST(TestMmanErrorMapping, MapCommonErrors) {
// Test that common Windows error codes map correctly to POSIX errno values.
// This verifies __map_mman_error() matches Arrow's WinErrorToErrno conventions.

// File/path not found errors
ASSERT_EQ(__map_mman_error(ERROR_FILE_NOT_FOUND, EPERM), ENOENT);
ASSERT_EQ(__map_mman_error(ERROR_PATH_NOT_FOUND, EPERM), ENOENT);

// Access/permission errors
ASSERT_EQ(__map_mman_error(ERROR_ACCESS_DENIED, EPERM), EACCES);
ASSERT_EQ(__map_mman_error(ERROR_SHARING_VIOLATION, EPERM), EACCES);
ASSERT_EQ(__map_mman_error(ERROR_LOCK_VIOLATION, EPERM), EACCES);

// Invalid handle errors
ASSERT_EQ(__map_mman_error(ERROR_INVALID_HANDLE, EPERM), EBADF);
ASSERT_EQ(__map_mman_error(ERROR_INVALID_TARGET_HANDLE, EPERM), EBADF);

// Invalid parameter/function errors
ASSERT_EQ(__map_mman_error(ERROR_INVALID_PARAMETER, EPERM), EINVAL);
ASSERT_EQ(__map_mman_error(ERROR_INVALID_FUNCTION, EPERM), EINVAL);

// Memory/resource errors
ASSERT_EQ(__map_mman_error(ERROR_ARENA_TRASHED, EPERM), ENOMEM);
ASSERT_EQ(__map_mman_error(ERROR_NOT_ENOUGH_MEMORY, EPERM), ENOMEM);
ASSERT_EQ(__map_mman_error(ERROR_INVALID_BLOCK, EPERM), ENOMEM);

ASSERT_EQ(__map_mman_error(ERROR_TOO_MANY_OPEN_FILES, EPERM), EMFILE);
ASSERT_EQ(__map_mman_error(ERROR_DISK_FULL, EPERM), ENOSPC);

// Zero error code
ASSERT_EQ(__map_mman_error(0, EPERM), 0);

// Unknown/unmapped error codes should return the default (deferr)
ASSERT_EQ(__map_mman_error(99999, EPERM), EPERM);
ASSERT_EQ(__map_mman_error(12345, EINVAL), EINVAL);
}
#endif // _WIN32

} // namespace io
} // namespace arrow
67 changes: 65 additions & 2 deletions cpp/src/arrow/io/mman.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,73 @@
# define FILE_MAP_EXECUTE 0x0020
#endif

// Map Windows error codes from GetLastError() to POSIX errno values.
//
// Parameters:
// err: Must be a DWORD value from GetLastError() (not HRESULT, not NTSTATUS).
// This function is called immediately after Windows API calls that set
// the last error via SetLastError() / GetLastError().
// deferr: Default errno value to return for unmapped errors. Callers pass
// EPERM as the default to maintain behavioral compatibility.
//
// Returns:
// POSIX errno value for known errors, or deferr for unmapped errors.
//
// Note: This function mirrors the mapping from Arrow's WinErrorToErrno() function
// (in arrow/util/io_util.cc) for consistency. All mapped error codes return the
// same errno values as WinErrorToErrno(). We cannot call WinErrorToErrno()
// directly because it's in an anonymous namespace and not exported, and this
// header must remain lightweight without additional dependencies.
//
// Unlike WinErrorToErrno() which returns 0 for unmapped errors, this function
// returns the deferr parameter to maintain compatibility with callers that
// explicitly pass a default (typically EPERM).
//
// The mapping covers common errors from memory mapping operations:
// - File/handle errors (ERROR_FILE_NOT_FOUND, ERROR_ACCESS_DENIED, etc.)
// - Memory/resource errors (ERROR_NOT_ENOUGH_MEMORY, etc.)
// - Parameter errors (ERROR_INVALID_PARAMETER, etc.)
static inline int __map_mman_error(const DWORD err, const int deferr) {
if (err == 0) return 0;
// TODO: implement
return err;

switch (err) {
// File/path not found errors - matches WinErrorToErrno
case ERROR_FILE_NOT_FOUND: // 2
case ERROR_PATH_NOT_FOUND: // 3
return ENOENT;

// Access/permission errors - matches WinErrorToErrno
case ERROR_ACCESS_DENIED: // 5
case ERROR_SHARING_VIOLATION: // 32
case ERROR_LOCK_VIOLATION: // 33
return EACCES;

// Invalid handle errors - matches WinErrorToErrno
case ERROR_INVALID_HANDLE: // 6
case ERROR_INVALID_TARGET_HANDLE: // 114
return EBADF;

// Invalid parameter/function errors - matches WinErrorToErrno
case ERROR_INVALID_PARAMETER: // 87
case ERROR_INVALID_FUNCTION: // 1
return EINVAL;

// Memory/resource errors - matches WinErrorToErrno
case ERROR_ARENA_TRASHED: // 7
case ERROR_NOT_ENOUGH_MEMORY: // 8
case ERROR_INVALID_BLOCK: // 9
return ENOMEM;

case ERROR_TOO_MANY_OPEN_FILES: // 4
return EMFILE;

case ERROR_DISK_FULL: // 112
return ENOSPC;

// Default: return the provided default errno for unmapped errors
default:
return deferr;
}
}

static inline DWORD __map_mmap_prot_page(const int prot) {
Expand Down
Loading