]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-104820: Fixes os.stat on Windows to better handle file systems that do not support...
authorSteve Dower <steve.dower@python.org>
Wed, 24 May 2023 23:16:13 +0000 (00:16 +0100)
committerGitHub <noreply@github.com>
Wed, 24 May 2023 23:16:13 +0000 (00:16 +0100)
Misc/NEWS.d/next/Windows/2023-05-24-21-00-57.gh-issue-104820.ibyrpp.rst [new file with mode: 0644]
Modules/posixmodule.c
Python/fileutils.c

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 (file)
index 0000000..5bdfbab
--- /dev/null
@@ -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.
index 2fe9973ef5bf7aa3a7fd5eb790baf3951b3485e0..294e9a2ca6e8fcc696c8197d3d7ec7e812893d8c 100644 (file)
@@ -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:
index 969b7163b5ac18d42a568063fc89103632116992..f137ee936502c1f28a1329a9eb90821ff7f172ef 100644 (file)
@@ -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;