@@ -1574,6 +1574,47 @@ def test_copyfile_socket(self): |
1574 | 1574 | self.assertRaisesRegex(shutil.SpecialFileError, 'is a socket', |
1575 | 1575 | shutil.copyfile, __file__, sock_path) |
1576 | 1576 |
|
| 1577 | + def _check_copyfile_symlink_to_special_file(self, target): |
| 1578 | + tmp_dir = self.mkdtemp() |
| 1579 | + src = os.path.join(tmp_dir, 'src') |
| 1580 | + dst = os.path.join(tmp_dir, 'dst') |
| 1581 | + os.symlink(target, src) |
| 1582 | + |
| 1583 | + shutil.copyfile(src, dst, follow_symlinks=False) |
| 1584 | + |
| 1585 | + self.assertTrue(os.path.islink(dst)) |
| 1586 | + self.assertEqual(os.readlink(dst), target) |
| 1587 | + |
| 1588 | + @os_helper.skip_unless_symlink |
| 1589 | + @unittest.skipUnless(os.path.exists('/dev/null'), 'requires /dev/null') |
| 1590 | + def test_copyfile_symlink_to_character_device(self): |
| 1591 | + self._check_copyfile_symlink_to_special_file('/dev/null') |
| 1592 | + |
| 1593 | + @os_helper.skip_unless_symlink |
| 1594 | + @unittest.skipUnless(hasattr(os, "mkfifo"), 'requires os.mkfifo()') |
| 1595 | + @unittest.skipIf(sys.platform == "vxworks", |
| 1596 | + "fifo requires special path on VxWorks") |
| 1597 | + def test_copyfile_symlink_to_named_pipe(self): |
| 1598 | + fifo_path = os.path.join(self.mkdtemp(), 'fifo') |
| 1599 | + try: |
| 1600 | + os.mkfifo(fifo_path) |
| 1601 | + except PermissionError as e: |
| 1602 | + self.skipTest('os.mkfifo(): %s' % e) |
| 1603 | + self._check_copyfile_symlink_to_special_file(fifo_path) |
| 1604 | + |
| 1605 | + @os_helper.skip_unless_symlink |
| 1606 | + @socket_helper.skip_unless_bind_unix_socket |
| 1607 | + def test_copyfile_symlink_to_socket(self): |
| 1608 | + sock_path = os.path.join(self.mkdtemp(), 'sock') |
| 1609 | + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
| 1610 | + self.addCleanup(sock.close) |
| 1611 | + try: |
| 1612 | + socket_helper.bind_unix_socket(sock, sock_path) |
| 1613 | + except OSError as e: |
| 1614 | + self.skipTest(f'cannot bind AF_UNIX socket: {e}') |
| 1615 | + self.addCleanup(os_helper.unlink, sock_path) |
| 1616 | + self._check_copyfile_symlink_to_special_file(sock_path) |
| 1617 | + |
1577 | 1618 | @unittest.skipUnless(os.path.exists('/dev/null'), 'requires /dev/null') |
1578 | 1619 | def test_copyfile_character_device(self): |
1579 | 1620 | self.assertRaisesRegex(shutil.SpecialFileError, 'is a character device', |
|