Eryk Sun <[email protected]> added the comment:
> 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.
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue38948>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com