bpo-46303: Don't define _Py_stat() and _Py_wstat() on Windows#30539
bpo-46303: Don't define _Py_stat() and _Py_wstat() on Windows#30539vstinner wants to merge 1 commit intopython:mainfrom vstinner:py_stat
Conversation
| static int | ||
| file_exists(PyObject *path) | ||
| { | ||
| wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL); | ||
| if (wpath == NULL) { | ||
| return -2; | ||
| } | ||
|
|
||
| DWORD attr = GetFileAttributesW(wpath); | ||
| int res = (attr != INVALID_FILE_ATTRIBUTES); | ||
|
|
||
| PyMem_Free(wpath); | ||
| return res; | ||
| } | ||
|
|
There was a problem hiding this comment.
GetFileAttributesW() doesn't follow a reparse point, such as a symlink, in the final component of the path. If tcl_library_path is the path of a symlink, checking existence of the target requires CreateFileW(wpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL). If the call succeeds, i.e. the call doesn't return INVALID_HANDLE_VALUE, the target exists and is accessible; close the handle.
There was a problem hiding this comment.
Here's the suggested implementation:
static int
file_exists(PyObject *path)
{
wchar_t *wpath = PyUnicode_AsWideCharString(path, NULL);
if (wpath == NULL) {
return -2;
}
HANDLE hfile = CreateFileW(wpath, 0, 0, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hfile != INVALID_HANDLE_VALUE) {
CloseHandle(hfile);
}
PyMem_Free(wpath);
return (hfile == INVALID_HANDLE_VALUE) ? -1 : 0;
}
This returns -1 when the file doesn't exist, since file_exists() replaces _Py_stat().
There was a problem hiding this comment.
I didn't expect that checking if a file exists would be so "complicated" :-) I'm waiting for @pacampbell to see if further changes are needed. Maybe this PR is not needed to build Python with clang.
There was a problem hiding this comment.
The GetFileAttributesW() call is like checking for existence with lstat() instead of stat(). That's probably good enough for tcl_library_path. Python's r"tcl\tclX.Y" is installed as a normal directory. However, I don't think the CreateFileW() call is complicated, and it makes file_exists() generally correct.
For the current implementation, the use of res == -1 in _get_tcl_lib_path() is wrong. The current implementation returns 1 if the file exists and 0 if it doesn't exist. This has to be fixed even if you keep the GetFileAttributesW() call.
|
https://bugs.python.org/issue46303#msg410377 is now fixed, this change is not needed. |
https://bugs.python.org/issue46303