diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py index 7ce99598ee8..12e516efdad 100644 --- a/Lib/test/test_os.py +++ b/Lib/test/test_os.py @@ -219,12 +219,12 @@ class StatAttributeTests(unittest.TestCase): os.unlink(self.fname) os.rmdir(support.TESTFN) - def test_stat_attributes(self): + def check_stat_attributes(self, fname): if not hasattr(os, "stat"): return import stat - result = os.stat(self.fname) + result = os.stat(fname) # Make sure direct access works self.assertEquals(result[stat.ST_SIZE], 3) @@ -281,6 +281,15 @@ class StatAttributeTests(unittest.TestCase): except TypeError: pass + def test_stat_attributes(self): + self.check_stat_attributes(self.fname) + + def test_stat_attributes_bytes(self): + try: + fname = self.fname.encode(sys.getfilesystemencoding()) + except UnicodeEncodeError: + self.skipTest("cannot encode %a for the filesystem" % self.fname) + self.check_stat_attributes(fname) def test_statvfs_attributes(self): if not hasattr(os, "statvfs"): diff --git a/Misc/NEWS b/Misc/NEWS index 82b54a8fae1..d9f8a949023 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -58,6 +58,8 @@ Core and Builtins Library ------- +- Issue #9908: Fix os.stat() on bytes paths under Windows 7. + - Issue #2643: msync() is not called anymore when deallocating an open mmap object, only munmap(). diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c index 59692622dae..a3e106a0c95 100644 --- a/Modules/posixmodule.c +++ b/Modules/posixmodule.c @@ -1152,7 +1152,7 @@ win32_stat(const char* path, struct win32_stat *result) NULL, /* security attributes */ OPEN_EXISTING, /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ - FILE_FLAG_BACKUP_SEMANTICS, + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, NULL); if(hFile == INVALID_HANDLE_VALUE) { @@ -1175,22 +1175,32 @@ win32_stat(const char* path, struct win32_stat *result) } code = attribute_data_to_stat(&info, result); } - - buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS); - if(!buf_size) return -1; - target_path = (char *)malloc((buf_size+1)*sizeof(char)); - result_length = Py_GetFinalPathNameByHandleA(hFile, target_path, - buf_size, VOLUME_NAME_DOS); - - if(!result_length) - return -1; + else { + /* We have a good handle to the target, use it to determine the target + path name (then we'll call lstat on it). */ + buf_size = Py_GetFinalPathNameByHandleA(hFile, 0, 0, VOLUME_NAME_DOS); + if(!buf_size) return -1; + /* Due to a slight discrepancy between GetFinalPathNameByHandleA + and GetFinalPathNameByHandleW, we must allocate one more byte + than reported. */ + target_path = (char *)malloc((buf_size+2)*sizeof(char)); + result_length = Py_GetFinalPathNameByHandleA(hFile, target_path, + buf_size+1, VOLUME_NAME_DOS); - if(!CloseHandle(hFile)) - return -1; + if(!result_length) { + free(target_path); + return -1; + } - target_path[result_length] = 0; - code = win32_lstat(target_path, result); - free(target_path); + if(!CloseHandle(hFile)) { + free(target_path); + return -1; + } + + target_path[result_length] = 0; + code = win32_lstat(target_path, result); + free(target_path); + } return code; } @@ -1254,11 +1264,15 @@ win32_stat_w(const wchar_t* path, struct win32_stat *result) result_length = Py_GetFinalPathNameByHandleW(hFile, target_path, buf_size, VOLUME_NAME_DOS); - if(!result_length) + if(!result_length) { + free(target_path); return -1; + } - if(!CloseHandle(hFile)) + if(!CloseHandle(hFile)) { + free(target_path); return -1; + } target_path[result_length] = 0; code = win32_lstat_w(target_path, result);