summaryrefslogtreecommitdiffstats
path: root/Lib/shutil.py
diff options
context:
space:
mode:
authorWinson Luk <winson.luk@gmail.com>2021-03-02 20:53:15 (GMT)
committerGitHub <noreply@github.com>2021-03-02 20:53:15 (GMT)
commit132131b404e06ee1a19b040a1f96cd1118abed0c (patch)
tree411a400f75855423fc83797fc407028e903f4ba9 /Lib/shutil.py
parentb36349a647b2bf8174f0e736a4fc347e92ae204e (diff)
downloadcpython-132131b404e06ee1a19b040a1f96cd1118abed0c.zip
cpython-132131b404e06ee1a19b040a1f96cd1118abed0c.tar.gz
cpython-132131b404e06ee1a19b040a1f96cd1118abed0c.tar.bz2
bpo-42782: Fail fast for permission errors in shutil.move() (GH-24001)
* Fail fast in shutil.move() to avoid creating destination directories on failure. Co-authored-by: Zackery Spytz <zspytz@gmail.com>
Diffstat (limited to 'Lib/shutil.py')
-rw-r--r--Lib/shutil.py11
1 files changed, 11 insertions, 0 deletions
diff --git a/Lib/shutil.py b/Lib/shutil.py
index f0e833d..89d924d 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -813,6 +813,12 @@ def move(src, dst, copy_function=copy2):
if _destinsrc(src, dst):
raise Error("Cannot move a directory '%s' into itself"
" '%s'." % (src, dst))
+ if (_is_immutable(src)
+ or (not os.access(src, os.W_OK) and os.listdir(src)
+ and sys.platform == 'darwin')):
+ raise PermissionError("Cannot move the non-empty directory "
+ "'%s': Lacking write permission to '%s'."
+ % (src, src))
copytree(src, real_dst, copy_function=copy_function,
symlinks=True)
rmtree(src)
@@ -830,6 +836,11 @@ def _destinsrc(src, dst):
dst += os.path.sep
return dst.startswith(src)
+def _is_immutable(src):
+ st = _stat(src)
+ immutable_states = [stat.UF_IMMUTABLE, stat.SF_IMMUTABLE]
+ return hasattr(st, 'st_flags') and st.st_flags in immutable_states
+
def _get_gid(name):
"""Returns a gid, given a group name."""
if getgrnam is None or name is None: