bpo-26660, bpo-35144: Fix permission errors in TemporaryDirectory cleanup. (GH-10320)

TemporaryDirectory.cleanup() failed when non-writeable or non-searchable
files or directories were created inside a temporary directory.
This commit is contained in:
Serhiy Storchaka 2019-05-31 11:30:37 +03:00 committed by GitHub
parent 38ab7d4721
commit e9b51c0ad8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 14 deletions

View file

@ -777,9 +777,39 @@ class TemporaryDirectory(object):
self, self._cleanup, self.name,
warn_message="Implicitly cleaning up {!r}".format(self))
@classmethod
def _rmtree(cls, name):
def onerror(func, path, exc_info):
if issubclass(exc_info[0], PermissionError):
def resetperms(path):
try:
_os.chflags(path, 0)
except AttributeError:
pass
_os.chmod(path, 0o700)
try:
if path != name:
resetperms(_os.path.dirname(path))
resetperms(path)
try:
_os.unlink(path)
# PermissionError is raised on FreeBSD for directories
except (IsADirectoryError, PermissionError):
cls._rmtree(path)
except FileNotFoundError:
pass
elif issubclass(exc_info[0], FileNotFoundError):
pass
else:
raise
_shutil.rmtree(name, onerror=onerror)
@classmethod
def _cleanup(cls, name, warn_message):
_shutil.rmtree(name)
cls._rmtree(name)
_warnings.warn(warn_message, ResourceWarning)
def __repr__(self):
@ -793,4 +823,4 @@ class TemporaryDirectory(object):
def cleanup(self):
if self._finalizer.detach():
_shutil.rmtree(self.name)
self._rmtree(self.name)