[issue38948] os.path.ismount() returns False for current working drive

2020-03-23 Thread Jonathan Hsu


Change by Jonathan Hsu :


--
nosy: +Jonathan Hsu

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38948] os.path.ismount() returns False for current working drive

2019-12-05 Thread Eryk Sun


Eryk Sun  added the comment:

> So essentially, you say the check should always be "ntpath.isdir(d) 

I forgot that ntpath.isdir is now genericpath.isdir, so that will work. The old 
nt._isdir wouldn't work because it was equivalent to an lstat. Apparently a 
vestigial import of nt._isdir remains in ntpath.py, even though nt._isdir was 
removed:

https://hg.python.org/cpython/file/v3.3.0/Lib/ntpath.py#l677

> On the other hand, this will make ntpath.ismount meaningless on POSIX, 
> as it will always require real access to the file system. Is it worth 
> having a "pure" implementation for best effort in this case? 

I'm not suggesting an existence check in POSIX. Whoever uses ntpath in POSIX 
must be aware that ntpath.ismount is useless for detecting Unix mount points. 
It's only useful for identifying potential mount points in a pure Windows path. 
I see no reason to break this use case.

For POSIX, I'd like ntpath._abspath_fallback to handle drive-relative paths, so 
we can fix the check in ismount to use `rest and rest in seps`. It seems wrong 
for _abspath_fallback("F:") to return the relative path "F:". No drives exist 
in POSIX, so it's harmless to assume that the working directory on each drive 
is the root directory, which is the default value in Windows anyway.

> Based on the splitdrive() 

Note that splitdrive currently doesn't support "UNC" device paths (issue 
37609). For example, "//?/UNC/server/share" splits as ("//?/UNC", 
"/server/share"). "GLOBAL" device paths also aren't supported, which I'd 
prefer, but it's less important because they're only useful rarely, and I don't 
know of an existing path library that handles them. splitdrive also doesn't 
support repeated separators between the server and share components, such as 
"//server///share", which GetFullPathNameW handles nowadays. Maybe it didn't 
circa NT 5.0. The only place that's strict is the UNC root, which must be 
exactly two separators. I uploaded an implementation to issue 37609 that 
supports "UNC" and "GLOBAL" device paths, with support for repeated separators. 
Here's a complex example split: ("//?///Global///UNC///server///share", 
"///path").

Anyway, ntpath.ismount needs to distinguish between UNC and "UNC" device paths 
vs all other device paths, because a root path is only optional in the UNC 
case. For example, "//?/C:" or "//?/BootPartition" is a volume device, and 
"//?C:/" or "//?/BootPartition/" is a filesystem mount point. In Windows we can 
detect that "//?/C:" or "//?/BootPartition" isn't a directory, but in POSIX we 
need to get it right as a pure path.

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38948] os.path.ismount() returns False for current working drive

2019-12-05 Thread Steve Dower


Steve Dower  added the comment:

> 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 would be a breaking change, 
> but I think it's important enough.

So essentially, you say the check should always be "ntpath.isdir(d) and 
ntpath.ismount(d)" (plus the non-breaking improvements to ismount)? And we 
should just do the isdir() inside ismount() because otherwise the result is 
nonsense.

I'm inclined to agree, and I'm not concerned about breaking a nonsense result. 

On the other hand, this will make ntpath.ismount meaningless on POSIX, as it 
will always require real access to the file system. Is it worth having a "pure" 
implementation for best effort in this case? Based on the splitdrive() patterns 
we support (plus the fixes to support them properly)?

--

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38948] os.path.ismount() returns False for current working drive

2019-12-05 Thread Eryk Sun


Eryk Sun  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:\server\share" 
resolves to opening "\Device\Mup\;LanmanRedirector\;X:\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 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue38948] os.path.ismount() returns False for current working drive

2019-12-02 Thread Steve Dower


Steve Dower  added the comment:

ntpath.ismount() is using a name-only check here, it never tries to resolve the 
path if splitdrive() returns (anything, one_of("", "/", "\\"))

Now it's not clear whether handling "" is intended there, but that's certainly 
the difference (Python 2 required exactly one character in that part). And it 
appears to be consistent back to 3.4, so I'm not sure we can or should fix 
anything. The only thing 'F:' can ever be is a mount point.

However, we should probably fix the fact that C: returns False. This is because 
we call abspath(path), and "x:" is a relative path. When the drive does not 
match the current working drive, you get "x:\\". But when it _does_ match, you 
get the current working directory, which (unless it's the root directory) is no 
longer a mount point.

Perhaps the best fix for that is to just say that "x:" is a relative path and 
hence never a mount point? Which would be the same as switching back to the 
Python 2 behaviour, but would be a much better reason.

--
nosy: +eryksun
title: os.path.ismount() returns true in python 3.7.4 and false in 2.7.14 -> 
os.path.ismount() returns False for current working drive
type:  -> behavior
versions: +Python 3.8, Python 3.9

___
Python tracker 

___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com