Eryk Sun <[email protected]> added the comment:
Where the POSIX specification uses the term "symbolic link" [1], it means one
and only one type of symlink, not multiple types of symlink with divergent
behavior depending on the context. To be consistent, only one type of Windows
reparse point [2] is classified as a POSIX symlink, the one that's designed to
behave like a POSIX symlink in the kernel and API: IO_REPARSE_TAG_SYMLINK.
It's particularly important that given os.path.islink is true, then os.readlink
and os.symlink can create an equivalent copy. This is only implemented for
IO_REPARSE_TAG_SYMLINK.
That said, Windows has a variety of filesystem link types, which it calls
name-surrogate reparse points. Of this set, in most systems you're only likely
to encounter IO_REPARSE_TAG_SYMLINK and IO_REPARSE_TAG_MOUNT_POINT. But
Microsoft has a growing list of name-surrogate types, including:
IO_REPARSE_TAG_IIS_CACHE, IO_REPARSE_TAG_GLOBAL_REPARSE (NPFS named-pipe
symlink from server silo into host silo), IO_REPARSE_TAG_WCI_LINK and
IO_REPARSE_TAG_WCI_TOMBSTONE (Windows container isolation),
IO_REPARSE_TAG_PROJFS_TOMBSTONE (Projected filesystem tombstone, such as in VFS
for Git), IO_REPARSE_TAG_LX_SYMLINK (WSL symlink created on a drvfs volume). In
some cases these are used transparently behind the scenes (e.g. tombstones that
mark deleted files), or there may be no handler for Windows callers (e.g. WSL
symlinks are meaningless in Windows).
Note that the latter list does not include IO_REPARSE_TAG_APPEXECLINK. Even
though "LINK" is in the name, this reparse point type is not any kind of
filesystem link in practice since it is not handled by the I/O manager or a
filter driver in the kernel. As discussed in my first message, all of the
intended behavior of an app-exec link is implemented instead by user-mode API
functions such as CreateProcessW. In that respect, an app-exec link is more
like a shell link (i.e. a LNK file), which gets handled by ShellExecuteExW. I
wouldn't expect the standard library to handle LNK files as symlinks.
---
The vast majority of registered reparse-point types are not link types (e.g.
cloud files are dehydrated placeholder reparse points). The base Windows API
has no special handling for the non-link cases. For example, MoveFileExW opens
a non-link reparse point as a regular file. If it operated on the reparse point
itself, like it does for a symbolic link, it would ignore the handler and
potentially break something.
This is why we can't even rename an app-exec link, since there's no handler for
the reparse tag:
>>> src = os.path.join(os.path.dirname(sys.executable), 'idle3.exe')
>>> dst = os.path.join(os.path.dirname(sys.executable), 'spam3.exe')
>>> try: os.rename(src, dst)
... except OSError as e: print('winerror:', e.winerror)
...
winerror: 1920
---
The standard library is not limited to just IO_REPARSE_TAG_SYMLINK links. It
supports the broader category of Windows name-surrogate links in certain cases.
For example, os.lstat doesn't follow them; os.readlink supports symlinks and
mountpoints [*]; os.unlink operates on symlinks and mountpoints; and
shutil.rmtree doesn't traverse mountpoints (unlike the POSIX implementation).
Caveat emptor regarding os.readlink, however. There are significant differences
between symlinks and mountpoints. They're designed to behave like Unix symlinks
and bind mountpoints, which have similar behavioral differences. Also,
mountpoints are always evaluated on the server, so a remote mountpoint *must*
be treated as opaque data [1]:
The following reparse tags, with the exception of
IO_REPARSE_TAG_SYMLINK, are processed on the server
and are not processed by a client after transmission
over the wire. Clients SHOULD treat associated
reparse data as opaque data.
---
[1]
https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap03.html#tag_21_03_00_75
[2]
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/c8e77b37-3909-4fe6-a4ea-2b9d423b1ee4
----------
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue41053>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com