]> granicus.if.org Git - python/commitdiff
Bug #1686475: Support stat'ing open files on Windows again.
authorMartin v. Löwis <martin@v.loewis.de>
Wed, 4 Apr 2007 18:30:56 +0000 (18:30 +0000)
committerMartin v. Löwis <martin@v.loewis.de>
Wed, 4 Apr 2007 18:30:56 +0000 (18:30 +0000)
Lib/test/test_os.py
Misc/NEWS
Modules/posixmodule.c

index 984484c4c36ec24828c361dd904bb7567dc4c045..69e456c1b3a6131fc74877b9e821e8ae37536e6f 100644 (file)
@@ -231,6 +231,15 @@ class StatAttributeTests(unittest.TestCase):
             os.utime(self.fname, (t1, t1))
             self.assertEquals(os.stat(self.fname).st_mtime, t1)
 
+        def test_1686475(self):
+            # Verify that an open file can be stat'ed
+            try:
+                os.stat(r"c:\pagefile.sys")
+            except WindowsError, e:
+                if e == 2: # file does not exist; cannot run test
+                    return
+                self.fail("Could not stat pagefile.sys")
+
 from test import mapping_tests
 
 class EnvironTests(mapping_tests.BasicTestMappingProtocol):
index 2f749af8946c8807c043039e81adbd0a940477a7..afbd326b23af0a866685e13c4e9d4876bb713927 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -134,6 +134,8 @@ Core and builtins
 Extension Modules
 -----------------
 
+- Bug #1686475: Support stat'ing open files on Windows again.
+
 - Bug #1647541: Array module's buffer interface can now handle empty arrays.
 
 - Bug #1693079: The array module can now successfully pickle empty arrays.
index 857d535279b99b5d9ffebc5ad5bb4ea08ffa0988..958fb63d316d5254f35bc29a9ae869d65a9243ba 100644 (file)
@@ -844,14 +844,48 @@ check_gfax()
        *(FARPROC*)&gfaxw = GetProcAddress(hKernel32, "GetFileAttributesExW");
 }
 
+static BOOL
+attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
+{
+       HANDLE hFindFile;
+       WIN32_FIND_DATAA FileData;
+       hFindFile = FindFirstFileA(pszFile, &FileData);
+       if (hFindFile == INVALID_HANDLE_VALUE)
+               return FALSE;
+       FindClose(hFindFile);
+       pfad->dwFileAttributes = FileData.dwFileAttributes;
+       pfad->ftCreationTime   = FileData.ftCreationTime;
+       pfad->ftLastAccessTime = FileData.ftLastAccessTime;
+       pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
+       pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
+       pfad->nFileSizeLow     = FileData.nFileSizeLow;
+       return TRUE;
+}
+
+static BOOL
+attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad)
+{
+       HANDLE hFindFile;
+       WIN32_FIND_DATAW FileData;
+       hFindFile = FindFirstFileW(pszFile, &FileData);
+       if (hFindFile == INVALID_HANDLE_VALUE)
+               return FALSE;
+       FindClose(hFindFile);
+       pfad->dwFileAttributes = FileData.dwFileAttributes;
+       pfad->ftCreationTime   = FileData.ftCreationTime;
+       pfad->ftLastAccessTime = FileData.ftLastAccessTime;
+       pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
+       pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
+       pfad->nFileSizeLow     = FileData.nFileSizeLow;
+       return TRUE;
+}
+
 static BOOL WINAPI
 Py_GetFileAttributesExA(LPCSTR pszFile, 
                       GET_FILEEX_INFO_LEVELS level,
                        LPVOID pv)
 {
        BOOL result;
-       HANDLE hFindFile;
-       WIN32_FIND_DATAA FileData;
        LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv;
        /* First try to use the system's implementation, if that is
           available and either succeeds to gives an error other than
@@ -873,17 +907,7 @@ Py_GetFileAttributesExA(LPCSTR pszFile,
           accept). */
        if (GetFileAttributesA(pszFile) == 0xFFFFFFFF)
                return FALSE;
-       hFindFile = FindFirstFileA(pszFile, &FileData);
-       if (hFindFile == INVALID_HANDLE_VALUE)
-               return FALSE;
-       FindClose(hFindFile);
-       pfad->dwFileAttributes = FileData.dwFileAttributes;
-       pfad->ftCreationTime   = FileData.ftCreationTime;
-       pfad->ftLastAccessTime = FileData.ftLastAccessTime;
-       pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
-       pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
-       pfad->nFileSizeLow     = FileData.nFileSizeLow;
-       return TRUE;
+       return attributes_from_dir(pszFile, pfad);
 }
 
 static BOOL WINAPI
@@ -892,8 +916,6 @@ Py_GetFileAttributesExW(LPCWSTR pszFile,
                        LPVOID pv)
 {
        BOOL result;
-       HANDLE hFindFile;
-       WIN32_FIND_DATAW FileData;
        LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv;
        /* First try to use the system's implementation, if that is
           available and either succeeds to gives an error other than
@@ -915,17 +937,7 @@ Py_GetFileAttributesExW(LPCWSTR pszFile,
           accept). */
        if (GetFileAttributesW(pszFile) == 0xFFFFFFFF)
                return FALSE;
-       hFindFile = FindFirstFileW(pszFile, &FileData);
-       if (hFindFile == INVALID_HANDLE_VALUE)
-               return FALSE;
-       FindClose(hFindFile);
-       pfad->dwFileAttributes = FileData.dwFileAttributes;
-       pfad->ftCreationTime   = FileData.ftCreationTime;
-       pfad->ftLastAccessTime = FileData.ftLastAccessTime;
-       pfad->ftLastWriteTime  = FileData.ftLastWriteTime;
-       pfad->nFileSizeHigh    = FileData.nFileSizeHigh;
-       pfad->nFileSizeLow     = FileData.nFileSizeLow;
-       return TRUE;
+       return attributes_from_dir_w(pszFile, pfad);
 }
 
 static int 
@@ -936,10 +948,20 @@ win32_stat(const char* path, struct win32_stat *result)
        char *dot;
        /* XXX not supported on Win95 and NT 3.x */
        if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
-               /* Protocol violation: we explicitly clear errno, instead of
-                  setting it to a POSIX error. Callers should use GetLastError. */
-               errno = 0;
-               return -1;
+               if (GetLastError() != ERROR_SHARING_VIOLATION) {
+                       /* Protocol violation: we explicitly clear errno, instead of
+                          setting it to a POSIX error. Callers should use GetLastError. */
+                       errno = 0;
+                       return -1;
+               } else {
+                       /* Could not get attributes on open file. Fall back to
+                          reading the directory. */
+                       if (!attributes_from_dir(path, &info)) {
+                               /* Very strange. This should not fail now */
+                               errno = 0;
+                               return -1;
+                       }
+               }
        }
        code = attribute_data_to_stat(&info, result);
        if (code != 0)
@@ -964,10 +986,20 @@ win32_wstat(const wchar_t* path, struct win32_stat *result)
        WIN32_FILE_ATTRIBUTE_DATA info;
        /* XXX not supported on Win95 and NT 3.x */
        if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
-               /* Protocol violation: we explicitly clear errno, instead of
-                  setting it to a POSIX error. Callers should use GetLastError. */
-               errno = 0;
-               return -1;
+               if (GetLastError() != ERROR_SHARING_VIOLATION) {
+                       /* Protocol violation: we explicitly clear errno, instead of
+                          setting it to a POSIX error. Callers should use GetLastError. */
+                       errno = 0;
+                       return -1;
+               } else {
+                       /* Could not get attributes on open file. Fall back to
+                          reading the directory. */
+                       if (!attributes_from_dir_w(path, &info)) {
+                               /* Very strange. This should not fail now */
+                               errno = 0;
+                               return -1;
+                       }
+               }
        }
        code = attribute_data_to_stat(&info, result);
        if (code < 0)