Skip to content

Commit cad7abf

Browse files
bpo-38030: Fix os.stat failures on block devices on Windows (GH-15681)
(cherry picked from commit 772ec0f) Co-authored-by: Steve Dower <[email protected]>
1 parent 5e194f5 commit cad7abf

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
@@ -1793,13 +1793,13 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
17931793
case ERROR_INVALID_PARAMETER:
17941794
case ERROR_INVALID_FUNCTION:
17951795
case ERROR_NOT_SUPPORTED:
1796-
retval = -1;
1796+
/* Volumes and physical disks are block devices, e.g.
1797+
\\.\C: and \\.\PhysicalDrive0. */
1798+
memset(result, 0, sizeof(*result));
1799+
result->st_mode = 0x6000; /* S_IFBLK */
17971800
goto cleanup;
17981801
}
1799-
/* Volumes and physical disks are block devices, e.g.
1800-
\\.\C: and \\.\PhysicalDrive0. */
1801-
memset(result, 0, sizeof(*result));
1802-
result->st_mode = 0x6000; /* S_IFBLK */
1802+
retval = -1;
18031803
goto cleanup;
18041804
}
18051805
}
@@ -1826,7 +1826,14 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
18261826

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

18321839
return retval;

0 commit comments

Comments
 (0)