Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (revision 85719) +++ Modules/posixmodule.c (working copy) @@ -934,7 +934,7 @@ } static int -attribute_data_to_stat(WIN32_FILE_ATTRIBUTE_DATA *info, struct win32_stat *result) +attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, struct win32_stat *result) { memset(result, 0, sizeof(*result)); result->st_mode = attributes_to_mode(info->dwFileAttributes); @@ -942,12 +942,12 @@ FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_ctime, &result->st_ctime_nsec); FILE_TIME_to_time_t_nsec(&info->ftLastWriteTime, &result->st_mtime, &result->st_mtime_nsec); FILE_TIME_to_time_t_nsec(&info->ftLastAccessTime, &result->st_atime, &result->st_atime_nsec); - + result->st_nlink = info->nNumberOfLinks; return 0; } static BOOL -attributes_from_dir(LPCSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +attributes_from_dir(LPCSTR pszFile, BY_HANDLE_FILE_INFORMATION *info) { HANDLE hFindFile; WIN32_FIND_DATAA FileData; @@ -955,17 +955,19 @@ 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; + memset(info, 0, sizeof(*info)); + info->dwFileAttributes = FileData.dwFileAttributes; + info->ftCreationTime = FileData.ftCreationTime; + info->ftLastAccessTime = FileData.ftLastAccessTime; + info->ftLastWriteTime = FileData.ftLastWriteTime; + info->nFileSizeHigh = FileData.nFileSizeHigh; + info->nFileSizeLow = FileData.nFileSizeLow; +/* info->nNumberOfLinks = 1; */ return TRUE; } static BOOL -attributes_from_dir_w(LPCWSTR pszFile, LPWIN32_FILE_ATTRIBUTE_DATA pfad) +attributes_from_dir_w(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info) { HANDLE hFindFile; WIN32_FIND_DATAW FileData; @@ -973,12 +975,14 @@ 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; + memset(info, 0, sizeof(*info)); + info->dwFileAttributes = FileData.dwFileAttributes; + info->ftCreationTime = FileData.ftCreationTime; + info->ftLastAccessTime = FileData.ftLastAccessTime; + info->ftLastWriteTime = FileData.ftLastWriteTime; + info->nFileSizeHigh = FileData.nFileSizeHigh; + info->nFileSizeLow = FileData.nFileSizeLow; +/* info->nNumberOfLinks = 1; */ return TRUE; } @@ -999,31 +1003,45 @@ static int win32_lstat(const char* path, struct win32_stat *result) { - WIN32_FILE_ATTRIBUTE_DATA info; - int code; - char *dot; + BOOL res; + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION info; + const char *dot; WIN32_FIND_DATAA find_data; HANDLE find_data_handle; - if (!GetFileAttributesExA(path, GetFileExInfoStandard, &info)) { - if (GetLastError() != ERROR_SHARING_VIOLATION) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - errno = 0; - return -1; - } else { + + hFile = CreateFileA( + path, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) { + /* Either the target doesn't exist, or we don't have access to + get a handle to it. If the former, we need to return an error. + If the latter, we can use attributes_from_dir. */ + if (GetLastError() != ERROR_SHARING_VIOLATION) + goto err; + else { /* Could not get attributes on open file. Fall back to reading the directory. */ - if (!attributes_from_dir(path, &info)) { + if (!attributes_from_dir(path, &info)) /* Very strange. This should not fail now */ - errno = 0; - return -1; - } + goto err; } } + else { + res = GetFileInformationByHandle(hFile, &info); + CloseHandle(hFile); + if (!res) + goto err; + } - code = attribute_data_to_stat(&info, result); - if (code != 0) - return code; + attribute_data_to_stat(&info, result); /* Get WIN32_FIND_DATA structure for the path to determine if it is a symlink */ @@ -1047,37 +1065,58 @@ stricmp(dot, ".exe") == 0 || stricmp(dot, ".com") == 0) result->st_mode |= 0111; } - return code; + return 0; + +err: + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; } static int win32_lstat_w(const wchar_t* path, struct win32_stat *result) { - int code; + BOOL res; + HANDLE hFile; + BY_HANDLE_FILE_INFORMATION info; const wchar_t *dot; - WIN32_FILE_ATTRIBUTE_DATA info; WIN32_FIND_DATAW find_data; HANDLE find_data_handle; - if (!GetFileAttributesExW(path, GetFileExInfoStandard, &info)) { - if (GetLastError() != ERROR_SHARING_VIOLATION) { - /* Protocol violation: we explicitly clear errno, instead of - setting it to a POSIX error. Callers should use GetLastError. */ - 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)) { + + hFile = CreateFileW( + path, + 0, /* desired access */ + 0, /* share mode */ + NULL, /* security attributes */ + OPEN_EXISTING, + /* FILE_FLAG_BACKUP_SEMANTICS is required to open a directory */ + FILE_ATTRIBUTE_NORMAL|FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, + NULL); + + if(hFile == INVALID_HANDLE_VALUE) { + /* Either the target doesn't exist, or we don't have access to + get a handle to it. If the former, we need to return an error. + If the latter, we can use attributes_from_dir. */ + if (GetLastError() != ERROR_SHARING_VIOLATION) + goto err; + 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; - } + goto err; } } - code = attribute_data_to_stat(&info, result); - if (code < 0) - return code; + else { + res = GetFileInformationByHandle(hFile, &info); + CloseHandle(hFile); + if (!res) + goto err; + } + attribute_data_to_stat(&info, result); + /* Get WIN32_FIND_DATA structure for the path to determine if it is a symlink */ if(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { @@ -1100,7 +1139,13 @@ _wcsicmp(dot, L".exe") == 0 || _wcsicmp(dot, L".com") == 0) result->st_mode |= 0111; } - return code; + return 0; + +err: + /* Protocol violation: we explicitly clear errno, instead of + setting it to a POSIX error. Callers should use GetLastError. */ + errno = 0; + return -1; } /* Grab GetFinalPathNameByHandle dynamically from kernel32 */ @@ -1138,7 +1183,7 @@ int buf_size; char *target_path; int result_length; - WIN32_FILE_ATTRIBUTE_DATA info; + BY_HANDLE_FILE_INFORMATION info; if(!check_GetFinalPathNameByHandle()) { /* if the OS doesn't have GetFinalPathNameByHandle, it doesn't @@ -1216,7 +1261,7 @@ int buf_size; wchar_t *target_path; int result_length; - WIN32_FILE_ATTRIBUTE_DATA info; + BY_HANDLE_FILE_INFORMATION info; if(!check_GetFinalPathNameByHandle()) { /* If the OS doesn't have GetFinalPathNameByHandle, it doesn't have @@ -1309,7 +1354,7 @@ if (type == FILE_TYPE_UNKNOWN) { DWORD error = GetLastError(); if (error != 0) { - return -1; + return -1; } /* else: valid but unknown file */ } @@ -1326,17 +1371,8 @@ return -1; } - /* similar to stat() */ - result->st_mode = attributes_to_mode(info.dwFileAttributes); - result->st_size = (((__int64)info.nFileSizeHigh)<<32) + info.nFileSizeLow; - FILE_TIME_to_time_t_nsec(&info.ftCreationTime, &result->st_ctime, - &result->st_ctime_nsec); - FILE_TIME_to_time_t_nsec(&info.ftLastWriteTime, &result->st_mtime, - &result->st_mtime_nsec); - FILE_TIME_to_time_t_nsec(&info.ftLastAccessTime, &result->st_atime, - &result->st_atime_nsec); + attribute_data_to_stat(&info, result); /* specific to fstat() */ - result->st_nlink = info.nNumberOfLinks; result->st_ino = (((__int64)info.nFileIndexHigh)<<32) + info.nFileIndexLow; return 0; }