Bug #1686475: Support stat'ing open files on Windows again.
This commit is contained in:
parent
5d2d2ef1f5
commit
8863544522
|
@ -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
|
||||||
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()
|
||||||
*(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)
|
||||||
|
|
Loading…
Reference in New Issue