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, jainankur, lazka, paul.moore, steve.dower, tim.golden, zach.ware
Date 2019-12-05.23:09:01
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1575587342.15.0.168193336262.issue38948@roundup.psfhosted.org>
In-reply-to
Content
> The only thing 'F:' can ever be is a mount point.

"F:" is a relative path that has to be resolved via abspath() (i.e. GetFullPathNameW in Windows) before we can determine whether it's a mount point. ntpath.ismount handles this correctly in 3.4+. 

The working directory on drive F: is the process working directory if it's the same drive, else it's the value of the "=F:" environment variable if defined, else it defaults to the root directory. The Windows API uses "=X:" environment variables, but it does not create them. They're optionally created by applications (e.g. CMD sets them, as does Python's os.chdir). Since they're just environment variables (albeit hidden because they begin with "="), per-drive working directories are inherited by child processes by default.

The main problem that I see here is that, in Windows (not POSIX), ntpath.ismount fails to verify that a potential mount point is an existing directory via os.stat and stat.S_ISDIR. This includes junctions that potentially target non-existing volumes (e.g. a junction to a removable volume that's unavailable or a volume with removable media that's not ready). This would be a breaking change, but I think it's important enough. Returning true for non-existing 'mount points' is nonsensical, since no filesystem actually mounts the path and the path itself may not even exist (e.g. an undefined drive or device). It needs to be and existing path in a device namespace (a device namespace is not necessarily a filesystem; all devices in NT have their own namespace, with a root path, whether mounted or not), and it has to at least be a subdirectory of a filesystem, if not the root directory. 

A common example of a mount point that's not at the root path of a device is a UNC share. For example, "\\;LanmanRedirector\;X:<logon ID>\server\share" resolves to opening "\Device\Mup\;LanmanRedirector\;X:<logon ID>\server\share", which is the form that's used for mapping an SMB share as a drive, except that a mapped drive can also target a subdirectory of a share. The opened path includes an explicit reference to the redirector device (to bypass prefix resolution), the drive and logon session for the cached connection (to bypass connecting), and an arbitrary number of prefix components (typically just "server\share"). 

Another related concern is the test for a root directory, `rest in seps`, which makes ntpath.ismount("F:") true in POSIX for the wrong reason. Since `seps` is a string, this check should actually be `rest and rest in seps' in order to avoid the vacuous truth when `rest` is an empty string. This problem is particular to POSIX because ntpath._abspath_fallback mishandles drive-relative paths. For example, ntpath.abspath("F:") returns "F:" in POSIX. It should special case a drive-relative path to insert a backslash (e.g. "F:" -> "F:\\", and "F:spam\\eggs" -> "F:\\spam\\eggs").

---

On the subject of junctions, a UNC path should not short-circuit out of checking for a junction, as it currently does. UNC paths can contain mount points, which get evaluated on the server.

In 3.8+, ntpath.ismount could also (and IMO should) support junctions that are bind mount points (i.e. mounting a subdirectory of a filesystem to a non-root path of a device) -- as posixpath.ismount does in POSIX. We already support bind mounts as subst and mapped drives and UNC shares, so it's just making ismount consistent, and for the better. This would require an os.lstat call to check st_file_attributes for stat.FILE_ATTRIBUTE_REPARSE_POINT and whether st_reparse_tag is stat.IO_REPARSE_TAG_MOUNT_POINT. It would still need an os.stat call and stat.S_ISDIR to verify that the target is an existing directory.
History
Date User Action Args
2019-12-05 23:09:02eryksunsetrecipients: + eryksun, paul.moore, tim.golden, zach.ware, steve.dower, lazka, jainankur
2019-12-05 23:09:02eryksunsetmessageid: <1575587342.15.0.168193336262.issue38948@roundup.psfhosted.org>
2019-12-05 23:09:02eryksunlinkissue38948 messages
2019-12-05 23:09:01eryksuncreate