-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
gh-108948: tarfile should handle sticky bit in FreeBSD #108950
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 1 commit
6a4be8f
50729f7
3587710
41491bb
4f6536d
fe7dfed
4009573
7b784b5
02d7c21
94efbbb
d1824c8
bd1dba7
417e31a
83c08fc
54f5548
b60ada6
5a51aab
cac6595
23a6fd5
060bcb2
5ae3e30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -691,6 +691,32 @@ def format_mtime(mtime): | |
tar.close() | ||
os_helper.rmtree(DIR) | ||
|
||
@unittest.skipUnless(hasattr(errno, "EFTYPE"), "errno.EFTYPE required") | ||
def test_extract_chmod_eftype(self): | ||
# Extracting a file as non-root should skip the sticky bit (gh-108948) | ||
# even on platforms where chmod fails with EFTYPE (i.e. FreeBSD). But | ||
# we need to take care that any other error is preserved. | ||
with ArchiveMaker() as arc: | ||
arc.add("sticky", mode="?rw-rw-rwt") | ||
tar = arc.open(errorlevel=2) | ||
DIR = os.path.join(TEMPDIR, "chmod") | ||
os.mkdir(DIR) | ||
sorcio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try: | ||
# this should not raise: | ||
tar.extract("sticky", DIR) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you check permissions of the created file? Please add also an empty line for readability. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Do you mean to stat the file and add an assertion that the flags are as expected? Sure, it's a good idea. The result would depend on whether the test code is run as root or not. Would it be fair to skip if running as root? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I expect that if run as root, the test sets the sticky bit. Otherwise, it doesn't. Python has a Cirrus CI job which runs the Python test suite on FreeBSD... as root! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, already did it in the new commit. Besides, pretty nice to have at least one test runner as root! (Well, assuming it works out with Cirrus credits) |
||
# but we can create a situation where it does raise: | ||
with unittest.mock.patch("os.chmod") as mock: | ||
eftype_error = OSError(errno.EFTYPE, "EFTYPE") | ||
other_error = OSError(errno.EPERM, "different error") | ||
mock.side_effect = [eftype_error, other_error] | ||
with self.assertRaises(tarfile.ExtractError) as excinfo: | ||
tar.extract("sticky", DIR) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please test somewhere that the ExtractError error message is "could not change mode"? Can you use a different name? extract("sticky", DIR) could also fail because the file already exists. Maybe add "sticky2" to the archive. |
||
self.assertEqual(excinfo.exception.__cause__, other_error) | ||
self.assertEqual(excinfo.exception.__cause__.__cause__, eftype_error) | ||
finally: | ||
os_helper.rmtree(DIR) | ||
tar.close() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead, you can use |
||
|
||
@os_helper.skip_unless_working_chmod | ||
def test_extract_directory(self): | ||
dirtype = "ustar/dirtype" | ||
|
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.
Would it make sense to mock this constant to test the code on other platforms?
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 decided to go with it. Maybe it's overkill for such a niche case, but more tests rarely hurt. All new tests never skip.