summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_shutil.py
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2021-03-03 15:37:20 (GMT)
committerGitHub <noreply@github.com>2021-03-03 15:37:20 (GMT)
commit59e857650cf49a5e28cb82acc2641b1b53efeeeb (patch)
tree79024f826abfdc586b56abeb54d8af374b88c5ab /Lib/test/test_shutil.py
parent9c6c5da55f4b9f4e5dde33d10adaf3d7ee824c11 (diff)
downloadcpython-59e857650cf49a5e28cb82acc2641b1b53efeeeb.zip
cpython-59e857650cf49a5e28cb82acc2641b1b53efeeeb.tar.gz
cpython-59e857650cf49a5e28cb82acc2641b1b53efeeeb.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> (cherry picked from commit 132131b404e06ee1a19b040a1f96cd1118abed0c) Co-authored-by: Winson Luk <winson.luk@gmail.com>
Diffstat (limited to 'Lib/test/test_shutil.py')
-rw-r--r--Lib/test/test_shutil.py37
1 files changed, 37 insertions, 0 deletions
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index 7730617..37940c8 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -33,6 +33,8 @@ from test import support
from test.support import TESTFN, FakePath
TESTFN2 = TESTFN + "2"
+TESTFN_SRC = TESTFN + "_SRC"
+TESTFN_DST = TESTFN + "_DST"
MACOS = sys.platform.startswith("darwin")
AIX = sys.platform[:3] == 'aix'
try:
@@ -2053,6 +2055,41 @@ class TestMove(unittest.TestCase):
self.assertEqual(len(moved), 3)
+ @unittest.skipUnless(hasattr(os, 'geteuid') and os.geteuid() == 0
+ and hasattr(os, 'lchflags')
+ and hasattr(stat, 'SF_IMMUTABLE')
+ and hasattr(stat, 'UF_OPAQUE'),
+ 'root privileges required')
+ def test_move_dir_permission_denied(self):
+ # bpo-42782: shutil.move should not create destination directories
+ # if the source directory cannot be removed.
+ try:
+ os.mkdir(TESTFN_SRC)
+ os.lchflags(TESTFN_SRC, stat.SF_IMMUTABLE)
+
+ # Testing on an empty immutable directory
+ # TESTFN_DST should not exist if shutil.move failed
+ self.assertRaises(PermissionError, shutil.move, TESTFN_SRC, TESTFN_DST)
+ self.assertFalse(TESTFN_DST in os.listdir())
+
+ # Create a file and keep the directory immutable
+ os.lchflags(TESTFN_SRC, stat.UF_OPAQUE)
+ os_helper.create_empty_file(os.path.join(TESTFN_SRC, 'child'))
+ os.lchflags(TESTFN_SRC, stat.SF_IMMUTABLE)
+
+ # Testing on a non-empty immutable directory
+ # TESTFN_DST should not exist if shutil.move failed
+ self.assertRaises(PermissionError, shutil.move, TESTFN_SRC, TESTFN_DST)
+ self.assertFalse(TESTFN_DST in os.listdir())
+ finally:
+ if os.path.exists(TESTFN_SRC):
+ os.lchflags(TESTFN_SRC, stat.UF_OPAQUE)
+ os_helper.rmtree(TESTFN_SRC)
+ if os.path.exists(TESTFN_DST):
+ os.lchflags(TESTFN_DST, stat.UF_OPAQUE)
+ os_helper.rmtree(TESTFN_DST)
+
+
class TestCopyFile(unittest.TestCase):
_delete = False