| 110 | |
| 111 | |
| 112 | class _WindowsFlavour(_Flavour): |
| 113 | # Reference for Windows paths can be found at |
| 114 | # http://msdn.microsoft.com/en-us/library/aa365247%28v=vs.85%29.aspx |
| 115 | |
| 116 | sep = '\\' |
| 117 | altsep = '/' |
| 118 | has_drv = True |
| 119 | pathmod = ntpath |
| 120 | |
| 121 | is_supported = (os.name == 'nt') |
| 122 | |
| 123 | drive_letters = set('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') |
| 124 | ext_namespace_prefix = '\\\\?\\' |
| 125 | |
| 126 | reserved_names = ( |
| 127 | {'CON', 'PRN', 'AUX', 'NUL', 'CONIN$', 'CONOUT$'} | |
| 128 | {'COM%s' % c for c in '123456789\xb9\xb2\xb3'} | |
| 129 | {'LPT%s' % c for c in '123456789\xb9\xb2\xb3'} |
| 130 | ) |
| 131 | |
| 132 | # Interesting findings about extended paths: |
| 133 | # * '\\?\c:\a' is an extended path, which bypasses normal Windows API |
| 134 | # path processing. Thus relative paths are not resolved and slash is not |
| 135 | # translated to backslash. It has the native NT path limit of 32767 |
| 136 | # characters, but a bit less after resolving device symbolic links, |
| 137 | # such as '\??\C:' => '\Device\HarddiskVolume2'. |
| 138 | # * '\\?\c:/a' looks for a device named 'C:/a' because slash is a |
| 139 | # regular name character in the object namespace. |
| 140 | # * '\\?\c:\foo/bar' is invalid because '/' is illegal in NT filesystems. |
| 141 | # The only path separator at the filesystem level is backslash. |
| 142 | # * '//?/c:\a' and '//?/c:/a' are effectively equivalent to '\\.\c:\a' and |
| 143 | # thus limited to MAX_PATH. |
| 144 | # * Prior to Windows 8, ANSI API bytes paths are limited to MAX_PATH, |
| 145 | # even with the '\\?\' prefix. |
| 146 | |
| 147 | def splitroot(self, part, sep=sep): |
| 148 | first = part[0:1] |
| 149 | second = part[1:2] |
| 150 | if (second == sep and first == sep): |
| 151 | # XXX extended paths should also disable the collapsing of "." |
| 152 | # components (according to MSDN docs). |
| 153 | prefix, part = self._split_extended_path(part) |
| 154 | first = part[0:1] |
| 155 | second = part[1:2] |
| 156 | else: |
| 157 | prefix = '' |
| 158 | third = part[2:3] |
| 159 | if (second == sep and first == sep and third != sep): |
| 160 | # is a UNC path: |
| 161 | # vvvvvvvvvvvvvvvvvvvvv root |
| 162 | # \\machine\mountpoint\directory\etc\... |
| 163 | # directory ^^^^^^^^^^^^^^ |
| 164 | index = part.find(sep, 2) |
| 165 | if index != -1: |
| 166 | index2 = part.find(sep, index + 1) |
| 167 | # a UNC path can't have two slashes in a row |
| 168 | # (after the initial two) |
| 169 | if index2 != index + 1: |