gh-82367: Use FindFirstFile Win32 API in ntpath.realpath() (GH-110298)

* Use `FindFirstFile` Win32 API to fix a bug where `ntpath.realpath()`
breaks out of traversing a series of paths where a (handled)
`ERROR_ACCESS_DENIED` or `ERROR_SHARING_VIOLATION` occurs.
* Update docs to reflect that `ntpath.realpath()` eliminates MS-DOS
style names.
This commit is contained in:
박문식 2023-10-05 23:49:07 +09:00 committed by GitHub
parent 2cb62c6437
commit d33aa18f15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 132 additions and 8 deletions

View file

@ -23,7 +23,6 @@ import stat
import genericpath
from genericpath import *
__all__ = ["normcase","isabs","join","splitdrive","splitroot","split","splitext",
"basename","dirname","commonprefix","getsize","getmtime",
"getatime","getctime", "islink","exists","lexists","isdir","isfile",
@ -601,7 +600,7 @@ else: # use native Windows method on Windows
return _abspath_fallback(path)
try:
from nt import _getfinalpathname, readlink as _nt_readlink
from nt import _findfirstfile, _getfinalpathname, readlink as _nt_readlink
except ImportError:
# realpath is a no-op on systems without _getfinalpathname support.
realpath = abspath
@ -688,10 +687,15 @@ else:
except OSError:
# If we fail to readlink(), let's keep traversing
pass
path, name = split(path)
# TODO (bpo-38186): Request the real file name from the directory
# entry using FindFirstFileW. For now, we will return the path
# as best we have it
# If we get these errors, try to get the real name of the file without accessing it.
if ex.winerror in (1, 5, 32, 50, 87, 1920, 1921):
try:
name = _findfirstfile(path)
path, _ = split(path)
except OSError:
path, name = split(path)
else:
path, name = split(path)
if path and not name:
return path + tail
tail = join(name, tail) if tail else name