#ifdef MS_WINDOWS
/* defined in fileutils.c */
void _Py_time_t_to_FILE_TIME(time_t, int, FILETIME *);
-void _Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *, ULONG,
- FILE_BASIC_INFO *, FILE_ID_INFO *,
- struct _Py_stat_struct *);
+void _Py_attribute_data_to_stat(FILE_STANDARD_INFO*, ULONG,
+ FILE_BASIC_INFO*, FILE_ID_INFO*,
+ struct _Py_stat_struct*);
void _Py_stat_basic_info_to_stat(FILE_STAT_BASIC_INFORMATION *,
struct _Py_stat_struct *);
#endif
static void
find_data_to_file_info(WIN32_FIND_DATAW *pFileData,
- BY_HANDLE_FILE_INFORMATION *info,
+ FILE_BASIC_INFO* basic_info,
+ FILE_STANDARD_INFO* standard_info,
ULONG *reparse_tag)
{
- memset(info, 0, sizeof(*info));
- info->dwFileAttributes = pFileData->dwFileAttributes;
- info->ftCreationTime = pFileData->ftCreationTime;
- info->ftLastAccessTime = pFileData->ftLastAccessTime;
- info->ftLastWriteTime = pFileData->ftLastWriteTime;
- info->nFileSizeHigh = pFileData->nFileSizeHigh;
- info->nFileSizeLow = pFileData->nFileSizeLow;
-/* info->nNumberOfLinks = 1; */
+ memset(basic_info, 0, sizeof(*basic_info));
+ memset(standard_info, 0, sizeof(*standard_info));
+
+ basic_info->FileAttributes = pFileData->dwFileAttributes;
+ basic_info->CreationTime.HighPart = pFileData->ftCreationTime.dwHighDateTime;
+ basic_info->CreationTime.LowPart = pFileData->ftCreationTime.dwLowDateTime;
+ basic_info->LastAccessTime.HighPart = pFileData->ftLastAccessTime.dwHighDateTime;
+ basic_info->LastAccessTime.LowPart = pFileData->ftLastAccessTime.dwLowDateTime;
+ basic_info->LastWriteTime.HighPart = pFileData->ftLastWriteTime.dwHighDateTime;
+ basic_info->LastWriteTime.LowPart = pFileData->ftLastWriteTime.dwLowDateTime;
+ standard_info->EndOfFile.HighPart = pFileData->nFileSizeHigh;
+ standard_info->EndOfFile.LowPart = pFileData->nFileSizeLow;
+
if (pFileData->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
*reparse_tag = pFileData->dwReserved0;
else
}
static BOOL
-attributes_from_dir(LPCWSTR pszFile, BY_HANDLE_FILE_INFORMATION *info, ULONG *reparse_tag)
+attributes_from_dir(LPCWSTR pszFile, FILE_BASIC_INFO* basic_info, FILE_STANDARD_INFO* standard_info, ULONG* reparse_tag)
{
HANDLE hFindFile;
WIN32_FIND_DATAW FileData;
return FALSE;
}
FindClose(hFindFile);
- find_data_to_file_info(&FileData, info, reparse_tag);
+ find_data_to_file_info(&FileData, basic_info, standard_info, reparse_tag);
return TRUE;
}
BOOL traverse)
{
HANDLE hFile;
- BY_HANDLE_FILE_INFORMATION fileInfo;
- FILE_BASIC_INFO basicInfo;
- FILE_BASIC_INFO *pBasicInfo = NULL;
- FILE_ID_INFO idInfo;
+ FILE_STANDARD_INFO standardInfo = {0};
+ FILE_BASIC_INFO basicInfo = {0};
+ FILE_ID_INFO idInfo = {0};
FILE_ID_INFO *pIdInfo = NULL;
FILE_ATTRIBUTE_TAG_INFO tagInfo = { 0 };
DWORD fileType, error;
case ERROR_ACCESS_DENIED: /* Cannot sync or read attributes. */
case ERROR_SHARING_VIOLATION: /* It's a paging file. */
/* Try reading the parent directory. */
- if (!attributes_from_dir(path, &fileInfo, &tagInfo.ReparseTag)) {
+ if (!attributes_from_dir(path, &basicInfo, &standardInfo, &tagInfo.ReparseTag)) {
/* Cannot read the parent directory. */
switch (GetLastError()) {
case ERROR_FILE_NOT_FOUND: /* File cannot be found */
return -1;
}
- if (fileInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+ if (basicInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
if (traverse ||
!IsReparseTagNameSurrogate(tagInfo.ReparseTag)) {
/* The stat call has to traverse but cannot, so fail. */
}
}
- if (!GetFileInformationByHandle(hFile, &fileInfo) ||
- !GetFileInformationByHandleEx(hFile, FileBasicInfo,
- &basicInfo, sizeof(basicInfo))) {
+ if (!GetFileInformationByHandleEx(hFile, FileStandardInfo, &standardInfo, sizeof(standardInfo)) ||
+ !GetFileInformationByHandleEx(hFile, FileBasicInfo, &basicInfo, sizeof(basicInfo))) {
switch (GetLastError()) {
case ERROR_INVALID_PARAMETER:
case ERROR_INVALID_FUNCTION:
goto cleanup;
}
- /* Successfully got FileBasicInfo, so we'll pass it along */
- pBasicInfo = &basicInfo;
-
if (GetFileInformationByHandleEx(hFile, FileIdInfo, &idInfo, sizeof(idInfo))) {
/* Successfully got FileIdInfo, so pass it along */
pIdInfo = &idInfo;
}
}
- _Py_attribute_data_to_stat(&fileInfo, tagInfo.ReparseTag, pBasicInfo, pIdInfo, result);
- update_st_mode_from_path(path, fileInfo.dwFileAttributes, result);
+ _Py_attribute_data_to_stat(&standardInfo, tagInfo.ReparseTag, &basicInfo, pIdInfo, result);
+ update_st_mode_from_path(path, basicInfo.FileAttributes, result);
cleanup:
if (hFile != INVALID_HANDLE_VALUE) {
DirEntry_from_find_data(PyObject *module, path_t *path, WIN32_FIND_DATAW *dataW)
{
DirEntry *entry;
- BY_HANDLE_FILE_INFORMATION file_info;
+ FILE_BASIC_INFO basic_info;
+ FILE_STANDARD_INFO standard_info;
ULONG reparse_tag;
wchar_t *joined_path;
goto error;
}
- find_data_to_file_info(dataW, &file_info, &reparse_tag);
- _Py_attribute_data_to_stat(&file_info, reparse_tag, NULL, NULL, &entry->win32_lstat);
+ find_data_to_file_info(dataW, &basic_info, &standard_info, &reparse_tag);
+ _Py_attribute_data_to_stat(&standard_info, reparse_tag, &basic_info, NULL, &entry->win32_lstat);
/* ctime is only deprecated from 3.12, so we copy birthtime across */
entry->win32_lstat.st_ctime = entry->win32_lstat.st_birthtime;
void
-_Py_attribute_data_to_stat(BY_HANDLE_FILE_INFORMATION *info, ULONG reparse_tag,
+_Py_attribute_data_to_stat(FILE_STANDARD_INFO* standard_info, ULONG reparse_tag,
FILE_BASIC_INFO *basic_info, FILE_ID_INFO *id_info,
struct _Py_stat_struct *result)
{
memset(result, 0, sizeof(*result));
- result->st_mode = attributes_to_mode(info->dwFileAttributes);
- result->st_size = (((__int64)info->nFileSizeHigh)<<32) + info->nFileSizeLow;
- result->st_dev = id_info ? id_info->VolumeSerialNumber : info->dwVolumeSerialNumber;
- result->st_rdev = 0;
+
+ result->st_size = standard_info->EndOfFile.QuadPart;
+ result->st_nlink = standard_info->NumberOfLinks;
+
/* st_ctime is deprecated, but we preserve the legacy value in our caller, not here */
- if (basic_info) {
- LARGE_INTEGER_to_time_t_nsec(&basic_info->CreationTime, &result->st_birthtime, &result->st_birthtime_nsec);
- LARGE_INTEGER_to_time_t_nsec(&basic_info->ChangeTime, &result->st_ctime, &result->st_ctime_nsec);
- LARGE_INTEGER_to_time_t_nsec(&basic_info->LastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
- LARGE_INTEGER_to_time_t_nsec(&basic_info->LastAccessTime, &result->st_atime, &result->st_atime_nsec);
- } else {
- FILE_TIME_to_time_t_nsec(&info->ftCreationTime, &result->st_birthtime, &result->st_birthtime_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;
+ LARGE_INTEGER_to_time_t_nsec(&basic_info->CreationTime, &result->st_birthtime, &result->st_birthtime_nsec);
+ LARGE_INTEGER_to_time_t_nsec(&basic_info->ChangeTime, &result->st_ctime, &result->st_ctime_nsec);
+ LARGE_INTEGER_to_time_t_nsec(&basic_info->LastWriteTime, &result->st_mtime, &result->st_mtime_nsec);
+ LARGE_INTEGER_to_time_t_nsec(&basic_info->LastAccessTime, &result->st_atime, &result->st_atime_nsec);
if (id_info) {
+ result->st_dev = id_info->VolumeSerialNumber;
id_128_to_ino file_id;
file_id.id = id_info->FileId;
result->st_ino = file_id.st_ino;
result->st_ino_high = file_id.st_ino_high;
}
- if (!result->st_ino && !result->st_ino_high) {
- /* should only occur for DirEntry_from_find_data, in which case the
- index is likely to be zero anyway. */
- result->st_ino = (((uint64_t)info->nFileIndexHigh) << 32) + info->nFileIndexLow;
- }
+
+ result->st_file_attributes = basic_info->FileAttributes;
+ result->st_mode = attributes_to_mode(result->st_file_attributes);
/* bpo-37834: Only actual symlinks set the S_IFLNK flag. But lstat() will
open other name surrogate reparse points without traversing them. To
detect/handle these, check st_file_attributes and st_reparse_tag. */
result->st_reparse_tag = reparse_tag;
- if (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT &&
+ if (result->st_file_attributes & FILE_ATTRIBUTE_REPARSE_POINT &&
reparse_tag == IO_REPARSE_TAG_SYMLINK) {
/* set the bits that make this a symlink */
result->st_mode = (result->st_mode & ~S_IFMT) | S_IFLNK;
}
- result->st_file_attributes = info->dwFileAttributes;
}
void
_Py_fstat_noraise(int fd, struct _Py_stat_struct *status)
{
#ifdef MS_WINDOWS
- BY_HANDLE_FILE_INFORMATION info;
- FILE_BASIC_INFO basicInfo;
- FILE_ID_INFO idInfo;
+ FILE_STANDARD_INFO standardInfo = {0};
+ FILE_BASIC_INFO basicInfo = {0};
+ FILE_ID_INFO idInfo = {0};
FILE_ID_INFO *pIdInfo = &idInfo;
HANDLE h;
int type;
return 0;
}
- if (!GetFileInformationByHandle(h, &info) ||
+ if (!GetFileInformationByHandleEx(h,FileStandardInfo, &standardInfo, sizeof(standardInfo)) ||
!GetFileInformationByHandleEx(h, FileBasicInfo, &basicInfo, sizeof(basicInfo))) {
/* The Win32 error is already set, but we also set errno for
callers who expect it */
pIdInfo = NULL;
}
- _Py_attribute_data_to_stat(&info, 0, &basicInfo, pIdInfo, status);
+ _Py_attribute_data_to_stat(&standardInfo, 0, &basicInfo, pIdInfo, status);
return 0;
#else
return fstat(fd, status);