mirror of
https://github.com/python/cpython.git
synced 2025-12-10 19:10:59 +00:00
gh-96290: Support partial/invalid UNC drives in ntpath.normpath() and splitdrive() (GH-100351)
This brings the Python implementation of `ntpath.normpath()` in line with the C implementation added in 99fcf15
Co-authored-by: Eryk Sun <eryksun@gmail.com>
This commit is contained in:
parent
eecd422d1b
commit
005e69403d
4 changed files with 55 additions and 46 deletions
|
|
@ -87,16 +87,20 @@ except ImportError:
|
|||
def isabs(s):
|
||||
"""Test whether a path is absolute"""
|
||||
s = os.fspath(s)
|
||||
# Paths beginning with \\?\ are always absolute, but do not
|
||||
# necessarily contain a drive.
|
||||
if isinstance(s, bytes):
|
||||
if s.replace(b'/', b'\\').startswith(b'\\\\?\\'):
|
||||
return True
|
||||
sep = b'\\'
|
||||
altsep = b'/'
|
||||
colon_sep = b':\\'
|
||||
else:
|
||||
if s.replace('/', '\\').startswith('\\\\?\\'):
|
||||
return True
|
||||
s = splitdrive(s)[1]
|
||||
return len(s) > 0 and s[0] and s[0] in _get_bothseps(s)
|
||||
sep = '\\'
|
||||
altsep = '/'
|
||||
colon_sep = ':\\'
|
||||
s = s[:3].replace(altsep, sep)
|
||||
# Absolute: UNC, device, and paths with a drive and root.
|
||||
# LEGACY BUG: isabs("/x") should be false since the path has no drive.
|
||||
if s.startswith(sep) or s.startswith(colon_sep, 1):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
# Join two (or more) paths.
|
||||
|
|
@ -172,34 +176,26 @@ def splitdrive(p):
|
|||
sep = b'\\'
|
||||
altsep = b'/'
|
||||
colon = b':'
|
||||
unc_prefix = b'\\\\?\\UNC'
|
||||
unc_prefix = b'\\\\?\\UNC\\'
|
||||
else:
|
||||
sep = '\\'
|
||||
altsep = '/'
|
||||
colon = ':'
|
||||
unc_prefix = '\\\\?\\UNC'
|
||||
unc_prefix = '\\\\?\\UNC\\'
|
||||
normp = p.replace(altsep, sep)
|
||||
if (normp[0:2] == sep*2) and (normp[2:3] != sep):
|
||||
# is a UNC path:
|
||||
# vvvvvvvvvvvvvvvvvvvv drive letter or UNC path
|
||||
# \\machine\mountpoint\directory\etc\...
|
||||
# directory ^^^^^^^^^^^^^^^
|
||||
if normp[:8].upper().rstrip(sep) == unc_prefix:
|
||||
start = 8
|
||||
else:
|
||||
start = 2
|
||||
if normp[0:2] == sep * 2:
|
||||
# UNC drives, e.g. \\server\share or \\?\UNC\server\share
|
||||
# Device drives, e.g. \\.\device or \\?\device
|
||||
start = 8 if normp[:8].upper() == unc_prefix else 2
|
||||
index = normp.find(sep, start)
|
||||
if index == -1:
|
||||
return p[:0], p
|
||||
return p, p[:0]
|
||||
index2 = normp.find(sep, index + 1)
|
||||
# a UNC path can't have two slashes in a row
|
||||
# (after the initial two)
|
||||
if index2 == index + 1:
|
||||
return p[:0], p
|
||||
if index2 == -1:
|
||||
index2 = len(p)
|
||||
return p, p[:0]
|
||||
return p[:index2], p[index2:]
|
||||
if normp[1:2] == colon:
|
||||
# Drive-letter drives, e.g. X:
|
||||
return p[:2], p[2:]
|
||||
return p[:0], p
|
||||
|
||||
|
|
@ -523,20 +519,11 @@ except ImportError:
|
|||
altsep = b'/'
|
||||
curdir = b'.'
|
||||
pardir = b'..'
|
||||
special_prefixes = (b'\\\\.\\', b'\\\\?\\')
|
||||
else:
|
||||
sep = '\\'
|
||||
altsep = '/'
|
||||
curdir = '.'
|
||||
pardir = '..'
|
||||
special_prefixes = ('\\\\.\\', '\\\\?\\')
|
||||
if path.startswith(special_prefixes):
|
||||
# in the case of paths with these prefixes:
|
||||
# \\.\ -> device names
|
||||
# \\?\ -> literal paths
|
||||
# do not do any normalization, but return the path
|
||||
# unchanged apart from the call to os.fspath()
|
||||
return path
|
||||
path = path.replace(altsep, sep)
|
||||
prefix, path = splitdrive(path)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue