Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 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
8 changes: 8 additions & 0 deletions Lib/tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
# Imports
#---------
from builtins import open as bltn_open
import errno
import sys
import os
import io
Expand Down Expand Up @@ -2569,6 +2570,13 @@ def chmod(self, tarinfo, targetpath):
try:
os.chmod(targetpath, tarinfo.mode)
except OSError as e:
if hasattr(errno, "EFTYPE") and e.errno == errno.EFTYPE:
# On FreeBSD, chmod fails when trying to set the sticky bit on
# a file as a normal user. It's a noop in most other platforms.
try:
os.chmod(targetpath, tarinfo.mode & ~stat.S_ISVTX)
except OSError as e:
raise ExtractError("could not change mode") from e
raise ExtractError("could not change mode") from e

def utime(self, tarinfo, targetpath):
Expand Down
11 changes: 10 additions & 1 deletion Lib/test/test_tarfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import re
import warnings
import stat
import errno

import unittest
import unittest.mock
Expand Down Expand Up @@ -3818,7 +3819,15 @@ def test_modes(self):
pass
new_mode = (os.stat(tmp_filename).st_mode
| stat.S_ISVTX | stat.S_ISGID | stat.S_ISUID)
os.chmod(tmp_filename, new_mode)
try:
os.chmod(tmp_filename, new_mode)
except OSError as err:
# FreeBSD fails with EFTYPE if sticky bit cannot be set, instead
# of ignoring it.
if hasattr(errno, "EFTYPE") and err.errno == errno.EFTYPE:
os.chmod(tmp_filename, new_mode & ~stat.S_ISVTX)
else:
raise
got_mode = os.stat(tmp_filename).st_mode
_t_file = 't' if (got_mode & stat.S_ISVTX) else 'x'
_suid_file = 's' if (got_mode & stat.S_ISUID) else 'x'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
On FreeBSD, :mod:`tarfile` will not attempt to set the sticky bit on extracted files when it's not possible, matching the behavior of other platforms.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum. I suggest to explain it differently.

:mod:`tarfile`: On FreeBSD, if the sticky bit cannot be set,
if the user is not root for example, clear the sticky bit,
matching the behavior of other platforms.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it would be worth it to add a note about the sticky bit in https://docs.python.org/dev/library/tarfile.html#tarfile.TarFile.extract documentation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with Ethan's suggestion for the blurb.

I also added a note, but under the filters documentation, so if a user searches for "sticky" or "bits" or similar keywords they find relevant information right there. I can change it or add more, of course.