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

Will backport to 2.5.
This commit is contained in:
Martin v. Löwis 2007-04-04 18:30:36 +00:00
parent 80e8c998a2
commit 3bf573f918
3 changed files with 77 additions and 34 deletions

View File

@ -240,6 +240,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):

View File

@ -589,6 +589,8 @@ Library
Extension Modules Extension Modules
----------------- -----------------
- Bug #1686475: Support stat'ing open files on Windows again.
- Patch #1185447: binascii.b2a_qp() now correctly quotes binary characters - Patch #1185447: binascii.b2a_qp() now correctly quotes binary characters
with ASCII value less than 32. Also, it correctly quotes dots only if 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 they occur on a single line, as opposed to the previous behavior of

View File

@ -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,
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,
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,
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)
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)
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)