|
33 | 33 | from test.support import TESTFN, FakePath
|
34 | 34 |
|
35 | 35 | TESTFN2 = TESTFN + "2"
|
| 36 | +TESTFN_SRC = TESTFN + "_SRC" |
| 37 | +TESTFN_DST = TESTFN + "_DST" |
36 | 38 | MACOS = sys.platform.startswith("darwin")
|
37 | 39 | AIX = sys.platform[:3] == 'aix'
|
38 | 40 | try:
|
@@ -2053,6 +2055,41 @@ def _copy(src, dst):
|
2053 | 2055 | self.assertEqual(len(moved), 3)
|
2054 | 2056 |
|
2055 | 2057 |
|
| 2058 | + @unittest.skipUnless(hasattr(os, 'geteuid') and os.geteuid() == 0 |
| 2059 | + and hasattr(os, 'lchflags') |
| 2060 | + and hasattr(stat, 'SF_IMMUTABLE') |
| 2061 | + and hasattr(stat, 'UF_OPAQUE'), |
| 2062 | + 'root privileges required') |
| 2063 | + def test_move_dir_permission_denied(self): |
| 2064 | + # bpo-42782: shutil.move should not create destination directories |
| 2065 | + # if the source directory cannot be removed. |
| 2066 | + try: |
| 2067 | + os.mkdir(TESTFN_SRC) |
| 2068 | + os.lchflags(TESTFN_SRC, stat.SF_IMMUTABLE) |
| 2069 | + |
| 2070 | + # Testing on an empty immutable directory |
| 2071 | + # TESTFN_DST should not exist if shutil.move failed |
| 2072 | + self.assertRaises(PermissionError, shutil.move, TESTFN_SRC, TESTFN_DST) |
| 2073 | + self.assertFalse(TESTFN_DST in os.listdir()) |
| 2074 | + |
| 2075 | + # Create a file and keep the directory immutable |
| 2076 | + os.lchflags(TESTFN_SRC, stat.UF_OPAQUE) |
| 2077 | + os_helper.create_empty_file(os.path.join(TESTFN_SRC, 'child')) |
| 2078 | + os.lchflags(TESTFN_SRC, stat.SF_IMMUTABLE) |
| 2079 | + |
| 2080 | + # Testing on a non-empty immutable directory |
| 2081 | + # TESTFN_DST should not exist if shutil.move failed |
| 2082 | + self.assertRaises(PermissionError, shutil.move, TESTFN_SRC, TESTFN_DST) |
| 2083 | + self.assertFalse(TESTFN_DST in os.listdir()) |
| 2084 | + finally: |
| 2085 | + if os.path.exists(TESTFN_SRC): |
| 2086 | + os.lchflags(TESTFN_SRC, stat.UF_OPAQUE) |
| 2087 | + os_helper.rmtree(TESTFN_SRC) |
| 2088 | + if os.path.exists(TESTFN_DST): |
| 2089 | + os.lchflags(TESTFN_DST, stat.UF_OPAQUE) |
| 2090 | + os_helper.rmtree(TESTFN_DST) |
| 2091 | + |
| 2092 | + |
2056 | 2093 | class TestCopyFile(unittest.TestCase):
|
2057 | 2094 |
|
2058 | 2095 | _delete = False
|
|
0 commit comments