mirror of https://github.com/python/cpython
gh-104820: Fixes os.stat on Windows to better handle file systems that do not support FileIdInformation (GH-104892)
This commit is contained in:
parent
087c1a6539
commit
6031727a37
|
@ -0,0 +1,2 @@
|
||||||
|
Fixes :func:`~os.stat` and related functions on file systems that do not
|
||||||
|
support file ID requests. This includes FAT32 and exFAT.
|
|
@ -1864,6 +1864,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
|
||||||
BY_HANDLE_FILE_INFORMATION fileInfo;
|
BY_HANDLE_FILE_INFORMATION fileInfo;
|
||||||
FILE_BASIC_INFO basicInfo;
|
FILE_BASIC_INFO basicInfo;
|
||||||
FILE_ID_INFO idInfo;
|
FILE_ID_INFO idInfo;
|
||||||
|
FILE_ID_INFO *pIdInfo = &idInfo;
|
||||||
FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
|
FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
|
||||||
DWORD fileType, error;
|
DWORD fileType, error;
|
||||||
BOOL isUnhandledTag = FALSE;
|
BOOL isUnhandledTag = FALSE;
|
||||||
|
@ -2000,9 +2001,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
|
||||||
|
|
||||||
if (!GetFileInformationByHandle(hFile, &fileInfo) ||
|
if (!GetFileInformationByHandle(hFile, &fileInfo) ||
|
||||||
!GetFileInformationByHandleEx(hFile, FileBasicInfo,
|
!GetFileInformationByHandleEx(hFile, FileBasicInfo,
|
||||||
&basicInfo, sizeof(basicInfo)) ||
|
&basicInfo, sizeof(basicInfo))) {
|
||||||
!GetFileInformationByHandleEx(hFile, FileIdInfo,
|
|
||||||
&idInfo, sizeof(idInfo))) {
|
|
||||||
switch (GetLastError()) {
|
switch (GetLastError()) {
|
||||||
case ERROR_INVALID_PARAMETER:
|
case ERROR_INVALID_PARAMETER:
|
||||||
case ERROR_INVALID_FUNCTION:
|
case ERROR_INVALID_FUNCTION:
|
||||||
|
@ -2018,7 +2017,12 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, &basicInfo, &idInfo, result);
|
if (!GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
|
||||||
|
/* Failed to get FileIdInfo, so do not pass it along */
|
||||||
|
pIdInfo = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, &basicInfo, pIdInfo, result);
|
||||||
update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
|
update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|
|
@ -1132,7 +1132,8 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
|
||||||
file_id.id = id_info->FileId;
|
file_id.id = id_info->FileId;
|
||||||
result->st_ino = file_id.st_ino;
|
result->st_ino = file_id.st_ino;
|
||||||
result->st_ino_high = file_id.st_ino_high;
|
result->st_ino_high = file_id.st_ino_high;
|
||||||
} else {
|
}
|
||||||
|
if (!result->st_ino && !result->st_ino_high) {
|
||||||
/* should only occur for DirEntry_from_find_data, in which case the
|
/* should only occur for DirEntry_from_find_data, in which case the
|
||||||
index is likely to be zero anyway. */
|
index is likely to be zero anyway. */
|
||||||
result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;
|
result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;
|
||||||
|
|
Loading…
Reference in New Issue