diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2024-01-12 15:53:27 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-12 15:53:27 (GMT) |
commit | 7b7cf75c027ba453c6b6e20d245e7338c70f0a03 (patch) | |
tree | 9488331e6fea687d7c776fd4a11cf8bb2d6cf825 /Lib/test | |
parent | eb22afb0042b09f05de5077c1947053dfbf7a5c0 (diff) | |
download | cpython-7b7cf75c027ba453c6b6e20d245e7338c70f0a03.zip cpython-7b7cf75c027ba453c6b6e20d245e7338c70f0a03.tar.gz cpython-7b7cf75c027ba453c6b6e20d245e7338c70f0a03.tar.bz2 |
gh-111877: Fixes stat() handling for inaccessible files on Windows (GH-113716)
(cherry picked from commit ed066481c76c6888ff5709f5b9f93b92c232a4a6)
Co-authored-by: Steve Dower <steve.dower@python.org>
Diffstat (limited to 'Lib/test')
-rw-r--r-- | Lib/test/test_os.py | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 2d94951..fc58f8d 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -3077,6 +3077,66 @@ class Win32NtTests(unittest.TestCase): except subprocess.TimeoutExpired: proc.terminate() + @support.requires_subprocess() + def test_stat_inaccessible_file(self): + filename = os_helper.TESTFN + ICACLS = os.path.expandvars(r"%SystemRoot%\System32\icacls.exe") + + with open(filename, "wb") as f: + f.write(b'Test data') + + stat1 = os.stat(filename) + + try: + # Remove all permissions from the file + subprocess.check_output([ICACLS, filename, "/inheritance:r"], + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as ex: + if support.verbose: + print(ICACLS, filename, "/inheritance:r", "failed.") + print(ex.stdout.decode("oem", "replace").rstrip()) + try: + os.unlink(filename) + except OSError: + pass + self.skipTest("Unable to create inaccessible file") + + def cleanup(): + # Give delete permission. We are the file owner, so we can do this + # even though we removed all permissions earlier. + subprocess.check_output([ICACLS, filename, "/grant", "Everyone:(D)"], + stderr=subprocess.STDOUT) + os.unlink(filename) + + self.addCleanup(cleanup) + + if support.verbose: + print("File:", filename) + print("stat with access:", stat1) + + # First test - we shouldn't raise here, because we still have access to + # the directory and can extract enough information from its metadata. + stat2 = os.stat(filename) + + if support.verbose: + print(" without access:", stat2) + + # We cannot get st_dev/st_ino, so ensure those are 0 or else our test + # is not set up correctly + self.assertEqual(0, stat2.st_dev) + self.assertEqual(0, stat2.st_ino) + + # st_mode and st_size should match (for a normal file, at least) + self.assertEqual(stat1.st_mode, stat2.st_mode) + self.assertEqual(stat1.st_size, stat2.st_size) + + # st_ctime and st_mtime should be the same + self.assertEqual(stat1.st_ctime, stat2.st_ctime) + self.assertEqual(stat1.st_mtime, stat2.st_mtime) + + # st_atime should be the same or later + self.assertGreaterEqual(stat1.st_atime, stat2.st_atime) + @os_helper.skip_unless_symlink class NonLocalSymlinkTests(unittest.TestCase): |