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 Jonathan Hsu, eryksun, jainankur, lazka, paul.moore, steve.dower, tim.golden, zach.ware
Date 2021-03-28.02:09:35
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1616897376.16.0.500281736523.issue38948@roundup.psfhosted.org>
In-reply-to
Content
Here's a concrete implementation of the above discussion. 

    _is_windows = (sys.platform == 'win32')

    def ismount(path):
        """Test whether a path is a mount point"""
        path = os.fspath(path)
        if isinstance(path, bytes):
            sep = b'\\'
            extended_devices = b'\\\\?\\'
            normal_devices = b'\\\\.\\'
            global_link = b'GLOBAL'
            unc_device = b'UNC'
        else:
            sep = '\\'
            extended_devices = '\\\\?\\'
            normal_devices = '\\\\.\\'
            global_link = 'GLOBAL'
            unc_device = 'UNC'
        # In Windows, require an existing, accessible directory.
        if _is_windows:
            if not isdir(path):
                return False
            try:
                s = os.lstat(path)
                if s.st_reparse_tag == stat.IO_REPARSE_TAG_MOUNT_POINT:
                    # isdir() verified the target directory.
                    return True
            except (OSError, ValueError):
                return False
        path = abspath(path)
        drive, drive_path = splitdrive(path)
        if not drive:
            return False
        # A drive root is a mount point.
        if drive_path == sep:
            return True
        # A root path is not required for a UNC drive.
        if not drive_path and drive[0] in sep:
            if not drive.startswith((extended_devices, normal_devices)):
                return True
            # Check for \\?\[Global]\UNC. Ignore repeated "Global" links.
            comps = [c.upper() for c in drive[4:].split(sep)]
            for c in comps:
                if c != global_link:
                    break
            if c == unc_device:
                return True
        return False

Removing the dependency on GetVolumePathNameW() also eliminates buggy behavior with substitute drives. For example, if substitute drive "W:" maps to r"C:\Windows", GetVolumePathNameW() mistakenly claims r"W:\System32" is a volume mount point.

In principle, this implementation also supports "\\?\[Global]\UNC\server\share" mount points on the "UNC" device, but it depends on fixing bpo-37609. The suggested rewrite for the latter issue also includes support for repeated slashes in a UNC drive, e.g. r"\\server\\\share" and r"\\?\\\Global\\\UNC\\\server\\\share" are valid.

For POSIX, ntpath._abspath_fallback() has to be fixed to correctly resolve drive-relative paths. For example:

    def _abspath_fallback(path):
        """Return the absolute version of a path."""
        path = os.fspath(path)
        if isinstance(path, bytes):
            sep = b'\\'
            colon = b':'
            cwd = os.getcwdb()
        else:
            sep = '\\'
            colon = ':'
            cwd = os.getcwd()
        if not isabs(path):
            # For a drive-relative path, default to the root directory
            # on the drive if the process working directory is on a
            # different drive.
            if path[1:2] == colon and path[:2].upper() != cwd[:2].upper():
                path = path[:2] + sep + path[2:]
            else:
                path = join(cwd, path)
        return normpath(path)

Since _abspath_fallback() is no longer needed in any version of Windows, maybe it should simply assume that the working drive is "C:" and the working directory on all drives is the root directory.
History
Date User Action Args
2021-03-28 02:09:36eryksunsetrecipients: + eryksun, paul.moore, tim.golden, zach.ware, steve.dower, lazka, jainankur, Jonathan Hsu
2021-03-28 02:09:36eryksunsetmessageid: <1616897376.16.0.500281736523.issue38948@roundup.psfhosted.org>
2021-03-28 02:09:36eryksunlinkissue38948 messages
2021-03-28 02:09:35eryksuncreate