| | 4473 | @symlink_test |
| | 4474 | @unittest.skipUnless(hasattr(os, 'chown'), "missing os.chown") |
| | 4475 | @unittest.skipUnless(hasattr(os, 'lchown'), "missing os.lchown") |
| | 4476 | @unittest.skipUnless(hasattr(os, 'geteuid'), "missing os.geteuid") |
| | 4477 | @support.subTests('link_type', (tarfile.SYMTYPE, tarfile.LNKTYPE)) |
| | 4478 | def test_chown_links_on_extract(self, link_type): |
| | 4479 | with ArchiveMaker() as arc: |
| | 4480 | arc.add("test.txt", |
| | 4481 | uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') |
| | 4482 | arc.add("link", |
| | 4483 | type=link_type, |
| | 4484 | linkname='test.txt', |
| | 4485 | uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') |
| | 4486 | |
| | 4487 | with ( |
| | 4488 | os_helper.temp_dir() as tmpdir, |
| | 4489 | arc.open() as tar, |
| | 4490 | unittest.mock.patch("os.chown") as mock_chown, |
| | 4491 | unittest.mock.patch("os.lchown") as mock_lchown, |
| | 4492 | unittest.mock.patch("os.geteuid") as mock_geteuid, |
| | 4493 | ): |
| | 4494 | # Set UID to 0 so chown() is attempted. |
| | 4495 | mock_geteuid.return_value = 0 |
| | 4496 | tar.extract("link", path=tmpdir, filter='data') |
| | 4497 | extract_path = os.path.join(tmpdir, "link") |
| | 4498 | |
| | 4499 | if link_type == tarfile.SYMTYPE: |
| | 4500 | mock_chown.assert_not_called() |
| | 4501 | mock_lchown.assert_called_once_with(extract_path, -1, -1) |
| | 4502 | else: |
| | 4503 | mock_chown.assert_has_calls([ |
| | 4504 | unittest.mock.call(extract_path, -1, -1), |
| | 4505 | unittest.mock.call(extract_path, -1, -1) |
| | 4506 | ]) |
| | 4507 | mock_lchown.assert_not_called() |
| | 4508 | |
| | 4509 | @symlink_test |
| | 4510 | @unittest.skipUnless(hasattr(os, 'chown'), "missing os.chown") |
| | 4511 | @unittest.skipUnless(hasattr(os, 'lchown'), "missing os.lchown") |
| | 4512 | @unittest.skipUnless(hasattr(os, 'geteuid'), "missing os.geteuid") |
| | 4513 | @support.subTests('link_type', (tarfile.SYMTYPE, tarfile.LNKTYPE)) |
| | 4514 | def test_chown_links_on_extractall(self, link_type): |
| | 4515 | with ArchiveMaker() as arc: |
| | 4516 | arc.add("test.txt", |
| | 4517 | uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') |
| | 4518 | arc.add("link", |
| | 4519 | type=link_type, |
| | 4520 | linkname='test.txt', |
| | 4521 | uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') |
| | 4522 | |
| | 4523 | with ( |
| | 4524 | os_helper.temp_dir() as tmpdir, |
| | 4525 | arc.open() as tar, |
| | 4526 | unittest.mock.patch("os.chown") as mock_chown, |
| | 4527 | unittest.mock.patch("os.lchown") as mock_lchown, |
| | 4528 | unittest.mock.patch("os.geteuid") as mock_geteuid, |
| | 4529 | ): |
| | 4530 | # Set UID to 0 so chown() is attempted. |
| | 4531 | mock_geteuid.return_value = 0 |
| | 4532 | tar.extractall(path=tmpdir, filter='data') |
| | 4533 | extract_link_path = os.path.join(tmpdir, "link") |
| | 4534 | extract_file_path = os.path.join(tmpdir, "test.txt") |
| | 4535 | |
| | 4536 | if link_type == tarfile.SYMTYPE: |
| | 4537 | mock_chown.assert_called_once_with(extract_file_path, -1, -1) |
| | 4538 | mock_lchown.assert_called_once_with(extract_link_path, -1, -1) |
| | 4539 | else: |
| | 4540 | mock_chown.assert_has_calls([ |
| | 4541 | unittest.mock.call(extract_file_path, -1, -1), |
| | 4542 | unittest.mock.call(extract_link_path, -1, -1) |
| | 4543 | ]) |
| | 4544 | mock_lchown.assert_not_called() |
| | 4545 | |
| | 4546 | def test_extract_filters_target(self): |
| | 4547 | # Test that when extract() falls back to extracting (rather than |
| | 4548 | # linking) a hardlink target, it filters the target. |
| | 4549 | with ArchiveMaker() as arc: |
| | 4550 | arc.add("target") |
| | 4551 | arc.add("link", hardlink_to="target") |
| | 4552 | def testing_filter(member, path): |
| | 4553 | if member.name == 'target': |
| | 4554 | # target: set read-only |
| | 4555 | return member.replace(mode=stat.S_IRUSR) |
| | 4556 | # link: don't overwrite the mode |
| | 4557 | return member.replace(mode=None) |
| | 4558 | tempdir = pathlib.Path(TEMPDIR) / 'extract' |
| | 4559 | with os_helper.temp_dir(tempdir), arc.open() as tar: |
| | 4560 | tar.extract("link", path=tempdir, filter=testing_filter) |
| | 4561 | path = tempdir / 'link' |
| | 4562 | if os_helper.can_chmod(): |
| | 4563 | self.assertFalse(path.stat().st_mode & stat.S_IWUSR) |
| | 4564 | |