summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2007-04-04 18:30:36 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2007-04-04 18:30:36 (GMT)
commit3bf573f918183af170ce2624dd61fe2969ee41aa (patch)
tree4483d8774e621486ee77db75989aa847c91351cd
parent80e8c998a27841ba2e36db897f9e0a76d46cfcae (diff)
downloadcpython-3bf573f918183af170ce2624dd61fe2969ee41aa.zip
cpython-3bf573f918183af170ce2624dd61fe2969ee41aa.tar.gz
cpython-3bf573f918183af170ce2624dd61fe2969ee41aa.tar.bz2
Bug #1686475: Support stat'ing open files on Windows again.
Will backport to 2.5.
-rw-r--r--Lib/test/test_os.py9
-rw-r--r--Misc/NEWS2
-rw-r--r--Modules/posixmodule.c100
3 files changed, 77 insertions, 34 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 40d7c3e..51fdc8a 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -240,6 +240,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):
diff --git a/Misc/NEWS b/Misc/NEWS
index d8f51bc..12d4413 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -589,6 +589,8 @@ Library
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
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index b9572cf..8fc9fa9 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -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)