[Python-checkins] r54685 - in python/trunk: Lib/test/test_os.py Misc/NEWS Modules/posixmodule.c

martin.v.loewis python-checkins at python.org
Wed Apr 4 20:30:42 CEST 2007


Author: martin.v.loewis
Date: Wed Apr  4 20:30:36 2007
New Revision: 54685

Modified:
   python/trunk/Lib/test/test_os.py
   python/trunk/Misc/NEWS
   python/trunk/Modules/posixmodule.c
Log:
Bug #1686475: Support stat'ing open files on Windows again.
Will backport to 2.5.

Modified: python/trunk/Lib/test/test_os.py
==============================================================================
--- python/trunk/Lib/test/test_os.py	(original)
+++ python/trunk/Lib/test/test_os.py	Wed Apr  4 20:30:36 2007
@@ -240,6 +240,15 @@
             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):

Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Wed Apr  4 20:30:36 2007
@@ -589,6 +589,8 @@
 Extension Modules
 -----------------
 
+- Bug #1686475: Support stat'ing open files on Windows again.
+
 - Patch #1185447: binascii.b2a_qp() now correctly quotes binary characters
   with ASCII value less than 32. Also, it correctly quotes dots only if
   they occur on a single line, as opposed to the previous behavior of

Modified: python/trunk/Modules/posixmodule.c
==============================================================================
--- python/trunk/Modules/posixmodule.c	(original)
+++ python/trunk/Modules/posixmodule.c	Wed Apr  4 20:30:36 2007
@@ -844,14 +844,48 @@
 	*(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 @@
 	   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 @@
                        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 @@
 	   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 @@
 	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_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)


More information about the Python-checkins mailing list