bpo-37834: Normalise handling of reparse points on Windows by zooba · Pull Request #15231 · python/cpython · GitHub
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 51 additions & 2 deletions Doc/library/os.rst
4 changes: 4 additions & 0 deletions Doc/library/shutil.rst
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ Directory and files operations
Added a symlink attack resistant version that is used automatically
if platform supports fd-based functions.

.. versionchanged:: 3.8
On Windows, will no longer delete the contents of a directory junction
before removing the junction.

.. attribute:: rmtree.avoids_symlink_attacks

Indicates whether the current platform and implementation provides a
Expand Down
10 changes: 10 additions & 0 deletions Doc/library/stat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -425,3 +425,13 @@ for more detail on the meaning of these constants.
FILE_ATTRIBUTE_VIRTUAL

.. versionadded:: 3.5

On Windows, the following constants are available for comparing against the
``st_reparse_tag`` member returned by :func:`os.lstat`. These are well-known
constants, but are not an exhaustive list.

.. data:: IO_REPARSE_TAG_SYMLINK
IO_REPARSE_TAG_MOUNT_POINT
IO_REPARSE_TAG_APPEXECLINK

.. versionadded:: 3.8
21 changes: 21 additions & 0 deletions Doc/whatsnew/3.8.rst
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,21 @@ A new :func:`os.memfd_create` function was added to wrap the
``memfd_create()`` syscall.
(Contributed by Zackery Spytz and Christian Heimes in :issue:`26836`.)

On Windows, much of the manual logic for handling reparse points (including
symlinks and directory junctions) has been delegated to the operating system.
Specifically, :func:`os.stat` will now traverse anything supported by the
operating system, while :func:`os.lstat` will only open reparse points that
identify as "name surrogates" while others are opened as for :func:`os.stat`.
In all cases, :attr:`stat_result.st_mode` will only have ``S_IFLNK`` set for
symbolic links and not other kinds of reparse points. To identify other kinds
of reparse point, check the new :attr:`stat_result.st_reparse_tag` attribute.

On Windows, :func:`os.readlink` is now able to read directory junctions. Note
that :func:`~os.path.islink` will return ``False`` for directory junctions,
and so code that checks ``islink`` first will continue to treat junctions as
directories, while code that handles errors from :func:`os.readlink` may now
treat junctions as links.


os.path
-------
Expand All @@ -824,6 +839,9 @@ characters or bytes unrepresentable at the OS level.
environment variable and does not use :envvar:`HOME`, which is not normally set
for regular user accounts.

:func:`~os.path.isdir` on Windows no longer returns true for a link to a
non-existent directory.

:func:`~os.path.realpath` on Windows now resolves reparse points, including
symlinks and directory junctions.

Expand Down Expand Up @@ -912,6 +930,9 @@ format for new archives to improve portability and standards conformance,
inherited from the corresponding change to the :mod:`tarfile` module.
(Contributed by C.A.M. Gerlach in :issue:`30661`.)

:func:`shutil.rmtree` on Windows now removes directory junctions without
recursively removing their contents first.


ssl
---
Expand Down
1 change: 1 addition & 0 deletions Include/fileutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ struct _Py_stat_struct {
time_t st_ctime;
int st_ctime_nsec;
unsigned long st_file_attributes;
unsigned long st_reparse_tag;
};
#else
# define _Py_stat_struct stat
Expand Down
48 changes: 41 additions & 7 deletions Lib/shutil.py
Loading