summaryrefslogtreecommitdiffstats
path: root/Lib/shutil.py
diff options
context:
space:
mode:
authorHynek Schlawack <hs@ox.cx>2012-06-23 18:28:32 (GMT)
committerHynek Schlawack <hs@ox.cx>2012-06-23 18:28:32 (GMT)
commit2100b42317ccbeed60fba90157b20ef4738f56f1 (patch)
tree0425868586b37998571b7bbcb131b4d4873929c6 /Lib/shutil.py
parent1641cea02b036b0a43b68f85bafa5b7e5a4ab97b (diff)
downloadcpython-2100b42317ccbeed60fba90157b20ef4738f56f1.zip
cpython-2100b42317ccbeed60fba90157b20ef4738f56f1.tar.gz
cpython-2100b42317ccbeed60fba90157b20ef4738f56f1.tar.bz2
#4489: Fix usage of fd-based functions to new api introduced earlier today
Also add an explicit test for safe implementation usage on supported platforms. As a side effect, this commit adds a module-level attribute 'rmtree_is_safe' which offers introspection whether the current rmtree implementation is safe against symlink attacks.
Diffstat (limited to 'Lib/shutil.py')
-rw-r--r--Lib/shutil.py23
1 files changed, 12 insertions, 11 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py
index 1b05484..c41046a 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -362,9 +362,9 @@ def _rmtree_unsafe(path, onerror):
_rmtree_unsafe(fullname, onerror)
else:
try:
- os.remove(fullname)
+ os.unlink(fullname)
except os.error:
- onerror(os.remove, fullname, sys.exc_info())
+ onerror(os.unlink, fullname, sys.exc_info())
try:
os.rmdir(path)
except os.error:
@@ -374,21 +374,21 @@ def _rmtree_unsafe(path, onerror):
def _rmtree_safe_fd(topfd, path, onerror):
names = []
try:
- names = os.flistdir(topfd)
+ names = os.listdir(topfd)
except os.error:
- onerror(os.flistdir, path, sys.exc_info())
+ onerror(os.listdir, path, sys.exc_info())
for name in names:
fullname = os.path.join(path, name)
try:
- orig_st = os.fstatat(topfd, name)
+ orig_st = os.stat(name, dir_fd=topfd)
mode = orig_st.st_mode
except os.error:
mode = 0
if stat.S_ISDIR(mode):
try:
- dirfd = os.openat(topfd, name, os.O_RDONLY)
+ dirfd = os.open(name, os.O_RDONLY, dir_fd=topfd)
except os.error:
- onerror(os.openat, fullname, sys.exc_info())
+ onerror(os.open, fullname, sys.exc_info())
else:
try:
if os.path.samestat(orig_st, os.fstat(dirfd)):
@@ -397,21 +397,22 @@ def _rmtree_safe_fd(topfd, path, onerror):
os.close(dirfd)
else:
try:
- os.unlinkat(topfd, name)
+ os.unlink(name, dir_fd=topfd)
except os.error:
- onerror(os.unlinkat, fullname, sys.exc_info())
+ onerror(os.unlink, fullname, sys.exc_info())
try:
os.rmdir(path)
except os.error:
onerror(os.rmdir, path, sys.exc_info())
-_use_fd_functions = hasattr(os, 'openat') and hasattr(os, 'unlinkat')
+rmtree_is_safe = _use_fd_functions = (os.unlink in os.supports_dir_fd and
+ os.open in os.supports_dir_fd)
def rmtree(path, ignore_errors=False, onerror=None):
"""Recursively delete a directory tree.
If ignore_errors is set, errors are ignored; otherwise, if onerror
is set, it is called to handle the error with arguments (func,
- path, exc_info) where func is os.listdir, os.remove, or os.rmdir;
+ path, exc_info) where func is platform and implementation dependent;
path is the argument to that function that caused it to fail; and
exc_info is a tuple returned by sys.exc_info(). If ignore_errors
is false and onerror is None, an exception is raised.