-
-
Notifications
You must be signed in to change notification settings - Fork 32.9k
bpo-32347: Emulate Libc copyfiles()'s st_flags logic on Darwin #4912
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dbb835d
b24bd53
b1c197e
6de062f
9fe54b5
38236ba
ef52332
eeaaff1
278fe8d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
""" | ||
|
||
import os | ||
import platform | ||
import sys | ||
import stat | ||
import fnmatch | ||
|
@@ -311,6 +312,31 @@ def _copyxattr(src, dst, *, follow_symlinks=True): | |
def _copyxattr(*args, **kwargs): | ||
pass | ||
|
||
if sys.platform == 'darwin': | ||
# As of macOS 10.10, the `copyfile` API changed to not copy certain flags. | ||
# This corresponds to kernel version 14.0. | ||
mac_ver = tuple(int(x) for x in os.uname().release.split('.')) | ||
if mac_ver >= (14, 0, 0): | ||
def _fix_flags(dst, flags, follow_symlinks): | ||
"""Perform any modifications to `flags` before they can be applied | ||
to `dst` with `chflags()`. | ||
|
||
""" | ||
# Based on copyfile's copyfile_stat() | ||
omit_flags = (stat.UF_TRACKED | stat.SF_RESTRICTED) | ||
add_flags = 0 | ||
|
||
# If the kernel automatically put SF_RESTRICTED on the destination | ||
# already, we don't want to clear it | ||
st = os.stat(dst, follow_symlinks=follow_symlinks) | ||
add_flags |= (st.st_flags & stat.SF_RESTRICTED) | ||
|
||
return (flags & ~omit_flags) | add_flags | ||
|
||
if '_fix_flags' not in vars(): | ||
|
||
def _fix_flags(dst, flags, *args, **kwargs): | ||
return flags | ||
|
||
def copystat(src, dst, *, follow_symlinks=True): | ||
"""Copy all stat info (mode bits, atime, mtime, flags) from src to dst. | ||
|
||
|
@@ -356,7 +382,8 @@ def lookup(name): | |
pass | ||
if hasattr(st, 'st_flags'): | ||
try: | ||
lookup("chflags")(dst, st.st_flags, follow_symlinks=follow) | ||
flags = _fix_flags(dst, st.st_flags, follow_symlinks=follow) | ||
lookup("chflags")(dst, flags, follow_symlinks=follow) | ||
except OSError as why: | ||
for err in 'EOPNOTSUPP', 'ENOTSUP': | ||
if hasattr(errno, err) and why.errno == getattr(errno, err): | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
``shutil.copystat`` now implements flag copy behavior from ``copyfile(3)`` | ||
on macOS 10.10 and above. Patch by Ryan Govostes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is needed, will macOS make files restricted when copying into special locations? The SIP feature only protects selected system files. Without this code the signature for this helper function could be simplified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic is the same as Apple's code, so I think it's better to keep it.