➜

This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author eryksun
Recipients eryksun, paul.moore, steve.dower, tim.golden, zach.ware
Date 2020-06-03.23:24:38
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <[email protected]>
In-reply-to
Content
ntpath.realpath fails to resolve the non-strict path of a broken relative symlink if the target is a rooted path. For example:

    >>> os.readlink('symlink')
    '\\broken\\link'
    >>> os.path.realpath('symlink')
    '\\broken\\link'

    >>> os.path.abspath('symlink')
    'C:\\Temp\\symlink'

The problem is that relative paths have to be specially handled by ntpath._readlink_deep, but ntpath.isabs incorrectly classifies r"\broken\link" as an absolute path. It's actually relative to the current device or drive in the access context. Other path libraries get this right, such as pathlib.Path.is_absolute and C++ path::is_absolute [1]. The documented behavior of ntpath.isabs (i.e. "begins with a (back)slash after chopping off a potential drive letter") isn't something that we can change. So ntpath._readlink_deep needs a private implementation of isabs. For example:

    def _isabs(s):
        s = os.fspath(s)
        seps = _get_bothseps(s)
        s = s[1:2] if (s and s[0] in seps) else splitdrive(s)[1]
        return bool(s) and s[0] in seps

This classifies UNC paths as absolute; rooted paths without a drive as relative; and otherwise depends on splitdrive() to get the root path, if any.

[1]: https://docs.microsoft.com/en-us/cpp/standard-library/path-class?view=vs-2019#is_absolute

----
Background

The target of a relative symlink gets evaluated against the hard path that's used to access the link. A hard path contains directories and mountpoints, but no symlinks. In particular, a rooted symlink target such as r"\spam\eggs" is relative to the root device of the hard path that's used to access the link. This may or may not be the device on which the link resides. It depends on how it's accessed. For example, if the volume that contains the r"\spam\eggs" link is accessed via its DOS device name "V:", then it resolves to r"V:\spam\eggs". Similarly, if the r"\spam\eggs" link is accessed via r"C:\Mount\VolumeSymlink", where "VolumeSymlink" is a directory symlink to "V:\\", then it also resolves to r"V:\spam\eggs". On the other hand, if the r"\spam\eggs" link is accessed via the mountpoint r"C:\Mount\VolumeMountpoint", then it resolves to r"C:\spam\eggs".
History
Date User Action Args
2020-06-03 23:24:39eryksunsetrecipients: + eryksun, paul.moore, tim.golden, zach.ware, steve.dower
2020-06-03 23:24:39eryksunsetmessageid: <[email protected]>
2020-06-03 23:24:38eryksunlinkissue40858 messages
2020-06-03 23:24:38eryksuncreate