[issue37705] winerror_to_errno implementation
Eryk Sun
report at bugs.python.org
Mon Jul 29 09:41:00 EDT 2019
New submission from Eryk Sun <eryksun at gmail.com>:
OSError and _Py_fstat_noraise rely on winerror_to_errno() in PC/errmap.h in order to translate a Windows system error code into a POSIX errno value. PC/errmap.h is supposed to be generated by PC/generrmap.c, which is based on the old CRT's _dosmapperr() function. However, this function isn't implemented in the Universal CRT, and ucrt's corresponding function, __acrt_errno_from_os_error, isn't exported for public use.
If generrmap.c is effectively dead, then it's no longer possible to add custom mappings there, as was done for issue 12802 (ERROR_DIRECTORY -> ENOTDIR) and issue 13063 (ERROR_NO_DATA -> EPIPE). Also, errmap.h hasn't been regenerated in 8 years, and since then the CRT added a new mapped value: ERROR_NO_UNICODE_TRANSLATION (1113) -> EILSEQ.
Unless someone can suggest a way to continue automatically generating errmap.h via generrmap.c, then I think winerror_to_errno should be manually implemented in a more readable and maintainable way, and updated from the ucrt source (ucrt\misc\errno.cpp) with each major Python release. The implementation could use a switch statement like it currently does, but with named error codes, grouped by result. For example:
int
winerror_to_errno(int winerror)
{
switch(winerror) {
case ERROR_FILE_NOT_FOUND: // 2
case ERROR_PATH_NOT_FOUND: // 3
case ERROR_INVALID_DRIVE: // 15
case ERROR_NO_MORE_FILES: // 18
case ERROR_BAD_NETPATH: // 53
case ERROR_BAD_NET_NAME: // 67
case ERROR_BAD_PATHNAME: // 161
case ERROR_FILENAME_EXCED_RANGE: // 206
return ENOENT;
case ERROR_BAD_ENVIRONMENT: // 10
return E2BIG;
case ERROR_BAD_FORMAT: // 11
case ERROR_INVALID_STARTING_CODESEG: // 188
case ERROR_INVALID_STACKSEG: // 189
case ERROR_INVALID_MODULETYPE: // 190
case ERROR_INVALID_EXE_SIGNATURE: // 191
case ERROR_EXE_MARKED_INVALID: // 192
case ERROR_BAD_EXE_FORMAT: // 193
case ERROR_ITERATED_DATA_EXCEEDS_64k: // 194
case ERROR_INVALID_MINALLOCSIZE: // 195
case ERROR_DYNLINK_FROM_INVALID_RING: // 196
case ERROR_IOPL_NOT_ENABLED: // 197
case ERROR_INVALID_SEGDPL: // 198
case ERROR_AUTODATASEG_EXCEEDS_64k: // 199
case ERROR_RING2SEG_MUST_BE_MOVABLE: // 200
case ERROR_RELOC_CHAIN_XEEDS_SEGLIM: // 201
case ERROR_INFLOOP_IN_RELOC_CHAIN: // 202
return ENOEXEC;
case ERROR_INVALID_HANDLE: // 6
case ERROR_INVALID_TARGET_HANDLE: // 114
case ERROR_DIRECT_ACCESS_HANDLE: // 130
return EBADF;
case ERROR_WAIT_NO_CHILDREN: // 128
case ERROR_CHILD_NOT_COMPLETE: // 129
return ECHILD;
case ERROR_NO_PROC_SLOTS: // 89
case ERROR_MAX_THRDS_REACHED: // 164
case ERROR_NESTING_NOT_ALLOWED: // 215
return EAGAIN;
case ERROR_ARENA_TRASHED: // 7
case ERROR_NOT_ENOUGH_MEMORY: // 8
case ERROR_INVALID_BLOCK: // 9
case ERROR_NOT_ENOUGH_QUOTA: // 1816
return ENOMEM;
case ERROR_ACCESS_DENIED: // 5
case ERROR_CURRENT_DIRECTORY: // 16
case ERROR_WRITE_PROTECT: // 19
case ERROR_BAD_UNIT: // 20
case ERROR_NOT_READY: // 21
case ERROR_BAD_COMMAND: // 22
case ERROR_CRC: // 23
case ERROR_BAD_LENGTH: // 24
case ERROR_SEEK: // 25
case ERROR_NOT_DOS_DISK: // 26
case ERROR_SECTOR_NOT_FOUND: // 27
case ERROR_OUT_OF_PAPER: // 28
case ERROR_WRITE_FAULT: // 29
case ERROR_READ_FAULT: // 30
case ERROR_GEN_FAILURE: // 31
case ERROR_SHARING_VIOLATION: // 32
case ERROR_LOCK_VIOLATION: // 33
case ERROR_WRONG_DISK: // 34
case ERROR_SHARING_BUFFER_EXCEEDED: // 36
case ERROR_NETWORK_ACCESS_DENIED: // 65
case ERROR_CANNOT_MAKE: // 82
case ERROR_FAIL_I24: // 83
case ERROR_DRIVE_LOCKED: // 108
case ERROR_SEEK_ON_DEVICE: // 132
case ERROR_NOT_LOCKED: // 158
case ERROR_LOCK_FAILED: // 167
case 35: // 35 [undefined]
return EACCES;
case ERROR_FILE_EXISTS: // 80
case ERROR_ALREADY_EXISTS: // 183
return EEXIST;
case ERROR_NOT_SAME_DEVICE: // 17
return EXDEV;
case ERROR_DIRECTORY: // 267 [bpo-12802]
return ENOTDIR;
case ERROR_TOO_MANY_OPEN_FILES: // 4
return EMFILE;
case ERROR_DISK_FULL: // 112
return ENOSPC;
case ERROR_BROKEN_PIPE: // 109
case ERROR_NO_DATA: // 232 [bpo-13063]
return EPIPE;
case ERROR_DIR_NOT_EMPTY: // 145
return ENOTEMPTY;
case ERROR_NO_UNICODE_TRANSLATION: // 1113
return EILSEQ;
case ERROR_INVALID_FUNCTION: // 1
case ERROR_INVALID_ACCESS: // 12
case ERROR_INVALID_DATA: // 13
case ERROR_INVALID_PARAMETER: // 87
case ERROR_NEGATIVE_SEEK: // 131
default:
return EINVAL;
}
}
----------
components: Interpreter Core, Windows
messages: 348661
nosy: eryksun, paul.moore, steve.dower, tim.golden, zach.ware
priority: normal
severity: normal
stage: needs patch
status: open
title: winerror_to_errno implementation
type: enhancement
versions: Python 3.8, Python 3.9
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue37705>
_______________________________________
More information about the Python-bugs-list
mailing list