Commit 88635445 authored by Martin v. Löwis's avatar Martin v. Löwis

Bug #1686475: Support stat'ing open files on Windows again.

parent 5d2d2ef1
...@@ -231,6 +231,15 @@ class StatAttributeTests(unittest.TestCase): ...@@ -231,6 +231,15 @@ class StatAttributeTests(unittest.TestCase):
os.utime(self.fname, (t1, t1)) os.utime(self.fname, (t1, t1))
self.assertEquals(os.stat(self.fname).st_mtime, 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 from test import mapping_tests
class EnvironTests(mapping_tests.BasicTestMappingProtocol): class EnvironTests(mapping_tests.BasicTestMappingProtocol):
......
...@@ -134,6 +134,8 @@ Core and builtins ...@@ -134,6 +134,8 @@ Core and builtins
Extension Modules 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 #1647541: Array module's buffer interface can now handle empty arrays.
- Bug #1693079: The array module can now successfully pickle empty arrays. - Bug #1693079: The array module can now successfully pickle empty arrays.
......
...@@ -844,14 +844,48 @@ check_gfax() ...@@ -844,14 +844,48 @@ check_gfax()
*(FARPROC*)&gfaxw = GetProcAddress(hKernel32, "GetFileAttributesExW"); *(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 static BOOL WINAPI
Py_GetFileAttributesExA(LPCSTR pszFile, Py_GetFileAttributesExA(LPCSTR pszFile,
GET_FILEEX_INFO_LEVELS level, GET_FILEEX_INFO_LEVELS level,
LPVOID pv) LPVOID pv)
{ {
BOOL result; BOOL result;
HANDLE hFindFile;
WIN32_FIND_DATAA FileData;
LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv;
/* First try to use the system's implementation, if that is /* First try to use the system's implementation, if that is
available and either succeeds to gives an error other than available and either succeeds to gives an error other than
...@@ -873,17 +907,7 @@ Py_GetFileAttributesExA(LPCSTR pszFile, ...@@ -873,17 +907,7 @@ Py_GetFileAttributesExA(LPCSTR pszFile,
accept). */ accept). */
if (GetFileAttributesA(pszFile) == 0xFFFFFFFF) if (GetFileAttributesA(pszFile) == 0xFFFFFFFF)
return FALSE; return FALSE;
hFindFile = FindFirstFileA(pszFile, &FileData); return attributes_from_dir(pszFile, pfad);
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 static BOOL WINAPI
...@@ -892,8 +916,6 @@ Py_GetFileAttributesExW(LPCWSTR pszFile, ...@@ -892,8 +916,6 @@ Py_GetFileAttributesExW(LPCWSTR pszFile,
LPVOID pv) LPVOID pv)
{ {
BOOL result; BOOL result;
HANDLE hFindFile;
WIN32_FIND_DATAW FileData;
LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv; LPWIN32_FILE_ATTRIBUTE_DATA pfad = pv;
/* First try to use the system's implementation, if that is /* First try to use the system's implementation, if that is
available and either succeeds to gives an error other than available and either succeeds to gives an error other than
...@@ -915,17 +937,7 @@ Py_GetFileAttributesExW(LPCWSTR pszFile, ...@@ -915,17 +937,7 @@ Py_GetFileAttributesExW(LPCWSTR pszFile,
accept). */ accept). */
if (GetFileAttributesW(pszFile) == 0xFFFFFFFF) if (GetFileAttributesW(pszFile) == 0xFFFFFFFF)
return FALSE; return FALSE;
hFindFile = FindFirstFileW(pszFile, &FileData); return attributes_from_dir_w(pszFile, pfad);
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 int static int
...@@ -936,10 +948,20 @@ win32_stat(const char* path, struct win32_stat *result) ...@@ -936,10 +948,20 @@ win32_stat(const char* path, struct win32_stat *result)
char *dot; char *dot;
/* XXX not supported on Win95 and NT 3.x */ /* XXX not supported on Win95 and NT 3.x */
if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { if (!Py_GetFileAttributesExA(path, GetFileExInfoStandard, &info)) {
/* Protocol violation: we explicitly clear errno, instead of if (GetLastError() != ERROR_SHARING_VIOLATION) {
setting it to a POSIX error. Callers should use GetLastError. */ /* Protocol violation: we explicitly clear errno, instead of
errno = 0; setting it to a POSIX error. Callers should use GetLastError. */
return -1; 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); code = attribute_data_to_stat(&info, result);
if (code != 0) if (code != 0)
...@@ -964,10 +986,20 @@ win32_wstat(const wchar_t* path, struct win32_stat *result) ...@@ -964,10 +986,20 @@ win32_wstat(const wchar_t* path, struct win32_stat *result)
WIN32_FILE_ATTRIBUTE_DATA info; WIN32_FILE_ATTRIBUTE_DATA info;
/* XXX not supported on Win95 and NT 3.x */ /* XXX not supported on Win95 and NT 3.x */
if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { if (!Py_GetFileAttributesExW(path, GetFileExInfoStandard, &info)) {
/* Protocol violation: we explicitly clear errno, instead of if (GetLastError() != ERROR_SHARING_VIOLATION) {
setting it to a POSIX error. Callers should use GetLastError. */ /* Protocol violation: we explicitly clear errno, instead of
errno = 0; setting it to a POSIX error. Callers should use GetLastError. */
return -1; 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); code = attribute_data_to_stat(&info, result);
if (code < 0) if (code < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment