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

This commit is contained in:
Martin v. Löwis 2007-04-04 18:30:56 +00:00
parent 5d2d2ef1f5
commit 8863544522
3 changed files with 77 additions and 34 deletions

View File

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

View File

@ -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.

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)