diff options
author | Senthil Kumaran <skumaran@gatech.edu> | 2021-03-03 16:04:00 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-03 16:04:00 (GMT) |
commit | bf566847f5a97e6ce391f8fb94185ee756cb94a2 (patch) | |
tree | 545235c3062cb627312aa45dd516c731ceb25ed7 /Lib/test/test_shutil.py | |
parent | 024325db5849c2cf1aa3b4c1013f73549712904e (diff) | |
download | cpython-bf566847f5a97e6ce391f8fb94185ee756cb94a2.zip cpython-bf566847f5a97e6ce391f8fb94185ee756cb94a2.tar.gz cpython-bf566847f5a97e6ce391f8fb94185ee756cb94a2.tar.bz2 |
[3.9] bpo-42782: Fail fast for permission errors in shutil.move() (GH-24001) (#24725)
* 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>
Co-authored-by: Winson Luk <winson.luk@gmail.com>
Diffstat (limited to 'Lib/test/test_shutil.py')
-rw-r--r-- | Lib/test/test_shutil.py | 37 |
1 files changed, 37 insertions, 0 deletions
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index e19af64..e378033 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: @@ -2083,6 +2085,41 @@ class TestMove(BaseTest, unittest.TestCase): os.rmdir(dst_dir) + @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): class Faux(object): |