bpo-38030: Fix os.stat failures on block devices on Windows (GH-15681)

This commit is contained in:
Steve Dower 2019-09-04 14:42:54 -07:00 committed by GitHub
parent 60bd1f88f2
commit 772ec0fad5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 6 deletions

View File

@ -591,6 +591,14 @@ class StatAttributeTests(unittest.TestCase):
result = os.stat(fname) result = os.stat(fname)
self.assertNotEqual(result.st_size, 0) self.assertNotEqual(result.st_size, 0)
@unittest.skipUnless(sys.platform == "win32", "Win32 specific tests")
def test_stat_block_device(self):
# bpo-38030: os.stat fails for block devices
# Test a filename like "//./C:"
fname = "//./" + os.path.splitdrive(os.getcwd())[0]
result = os.stat(fname)
self.assertEqual(result.st_mode, stat.S_IFBLK)
class UtimeTests(unittest.TestCase): class UtimeTests(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -0,0 +1 @@
Fixes :func:`os.stat` failing for block devices on Windows

View File

@ -1794,13 +1794,13 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
case ERROR_INVALID_PARAMETER: case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_FUNCTION: case ERROR_INVALID_FUNCTION:
case ERROR_NOT_SUPPORTED: case ERROR_NOT_SUPPORTED:
retval = -1; /* Volumes and physical disks are block devices, e.g.
\\.\C: and \\.\PhysicalDrive0. */
memset(result, 0, sizeof(*result));
result->st_mode = 0x6000; /* S_IFBLK */
goto cleanup; goto cleanup;
} }
/* Volumes and physical disks are block devices, e.g. retval = -1;
\\.\C: and \\.\PhysicalDrive0. */
memset(result, 0, sizeof(*result));
result->st_mode = 0x6000; /* S_IFBLK */
goto cleanup; goto cleanup;
} }
} }
@ -1827,7 +1827,14 @@ win32_xstat_impl(const wchar_t *path, struct _Py_stat_struct *result,
cleanup: cleanup:
if (hFile != INVALID_HANDLE_VALUE) { if (hFile != INVALID_HANDLE_VALUE) {
CloseHandle(hFile); /* Preserve last error if we are failing */
error = retval ? GetLastError() : 0;
if (!CloseHandle(hFile)) {
retval = -1;
} else if (retval) {
/* Restore last error */
SetLastError(error);
}
} }
return retval; return retval;