From: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> Date: Mon, 29 May 2023 16:57:04 +0000 (-0700) Subject: gh-104820: Fixes os.stat on Windows to better handle file systems that do not support... X-Git-Tag: v3.12.0b2~57 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=68bf3fe0e4221bd33823b727af1f70708bdb8f29;p=thirdparty%2FPython%2Fcpython.git gh-104820: Fixes os.stat on Windows to better handle file systems that do not support FileIdInformation (GH-104892) (cherry picked from commit 6031727a37c6003f78e3b0c7414a0a214855dd08) Co-authored-by: Steve Dower --- diff --git a/Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst b/Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst new file mode 100644 index 000000000000..5bdfbabfaf28 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst @@ -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. diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 77df9e7b8a5b..abc50b4d335b 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1864,6 +1864,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result, BY_HANDLE_FILE_INFORMATION fileInfo; FILE_BASIC_INFO basicInfo; FILE_ID_INFO idInfo; + FILE_ID_INFO *pIdInfo = &idInfo; FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 }; DWORD fileType, error; BOOL isUnhandledTag = FALSE; @@ -2000,9 +2001,7 @@ win32_xstat_slow_impl(const wchar_t *path, struct _Py_stat_struct *result, if (!GetFileInformationByHandle(hFile, &fileInfo) || !GetFileInformationByHandleEx(hFile, FileBasicInfo, - &basicInfo, sizeof(basicInfo)) || - !GetFileInformationByHandleEx(hFile, FileIdInfo, - &idInfo, sizeof(idInfo))) { + &basicInfo, sizeof(basicInfo))) { switch (GetLastError()) { case ERROR_INVALID_PARAMETER: 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); cleanup: diff --git a/Python/fileutils.c b/Python/fileutils.c index 969b7163b5ac..f137ee936502 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -1132,7 +1132,8 @@ _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag, file_id.id = id_info->FileId; result->st_ino = file_id.st_ino; 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 index is likely to be zero anyway. */ result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;