diff options
author | Steve Dower <steve.dower@python.org> | 2023-12-13 23:41:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-13 23:41:43 (GMT) |
commit | fddc829236d7b29a522a2160e57b2d7ca23b9b95 (patch) | |
tree | aaad0e053b6b2df28cbb56ce58138ffef6f6c41e /Modules/getpath.c | |
parent | 41c18aacc7a6082fbd9b08697c4d6180a9b62265 (diff) | |
download | cpython-fddc829236d7b29a522a2160e57b2d7ca23b9b95.zip cpython-fddc829236d7b29a522a2160e57b2d7ca23b9b95.tar.gz cpython-fddc829236d7b29a522a2160e57b2d7ca23b9b95.tar.bz2 |
gh-86179: Implement realpath() on Windows for getpath.py calculations (GH-113033)
Diffstat (limited to 'Modules/getpath.c')
-rw-r--r-- | Modules/getpath.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/Modules/getpath.c b/Modules/getpath.c index 6c1078b..422056b 100644 --- a/Modules/getpath.c +++ b/Modules/getpath.c @@ -502,6 +502,45 @@ done: PyMem_Free((void *)path); PyMem_Free((void *)narrow); return r; +#elif defined(MS_WINDOWS) + HANDLE hFile; + wchar_t resolved[MAXPATHLEN+1]; + int len = 0, err; + PyObject *result; + + wchar_t *path = PyUnicode_AsWideCharString(pathobj, NULL); + if (!path) { + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + hFile = CreateFileW(path, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + len = GetFinalPathNameByHandleW(hFile, resolved, MAXPATHLEN, VOLUME_NAME_DOS); + err = len ? 0 : GetLastError(); + CloseHandle(hFile); + } else { + err = GetLastError(); + } + Py_END_ALLOW_THREADS + + if (err) { + PyErr_SetFromWindowsErr(err); + result = NULL; + } else if (len <= MAXPATHLEN) { + const wchar_t *p = resolved; + if (0 == wcsncmp(p, L"\\\\?\\", 4)) { + if (GetFileAttributesW(&p[4]) != INVALID_FILE_ATTRIBUTES) { + p += 4; + len -= 4; + } + } + result = PyUnicode_FromWideChar(p, len); + } else { + result = Py_NewRef(pathobj); + } + PyMem_Free(path); + return result; #endif return Py_NewRef(pathobj); |