Skip to content

Commit 772ec0f

Browse files
authored
bpo-38030: Fix os.stat failures on block devices on Windows (GH-15681)
1 parent 60bd1f8 commit 772ec0f

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

Lib/test/test_os.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,14 @@ def test_access_denied(self):
591591
result = os.stat(fname)
592592
self.assertNotEqual(result.st_size, 0)
593593

594+
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
595+
def test_stat_block_device(self):
596+
# bpo-38030: os.stat fails for block devices
597+
# Test a filename like "//./C:"
598+
fname = "//./" + os.path.splitdrive(os.getcwd())[0]
599+
result = os.stat(fname)
600+
self.assertEqual(result.st_mode, stat.S_IFBLK)
601+
594602

595603
class UtimeTests(unittest.TestCase):
596604
def setUp(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixes :func:`os.stat` failing for block devices on Windows

Modules/posixmodule.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,13 +1794,13 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
17941794
case ERROR_INVALID_PARAMETER:
17951795
case ERROR_INVALID_FUNCTION:
17961796
case ERROR_NOT_SUPPORTED:
1797-
retval = -1;
1797+
/* Volumes and physical disks are block devices, e.g.
1798+
\\.\C: and \\.\PhysicalDrive0. */
1799+
memset(result, 0, sizeof(*result));
1800+
result->st_mode = 0x6000; /* S_IFBLK */
17981801
goto cleanup;
17991802
}
1800-
/* Volumes and physical disks are block devices, e.g.
1801-
\\.\C: and \\.\PhysicalDrive0. */
1802-
memset(result, 0, sizeof(*result));
1803-
result->st_mode = 0x6000; /* S_IFBLK */
1803+
retval = -1;
18041804
goto cleanup;
18051805
}
18061806
}
@@ -1827,7 +1827,14 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
18271827

18281828
cleanup:
18291829
if (hFile != INVALID_HANDLE_VALUE) {
1830-
CloseHandle(hFile);
1830+
/* Preserve last error if we are failing */
1831+
error = retval ? GetLastError() : 0;
1832+
if (!CloseHandle(hFile)) {
1833+
retval = -1;
1834+
} else if (retval) {
1835+
/* Restore last error */
1836+
SetLastError(error);
1837+
}
18311838
}
18321839

18331840
return retval;

0 commit comments

Comments
 (0)