Ported from _Py_attribute_data_to_stat (fileutils.c) Converts BY_HANDLE_FILE_INFORMATION to StatStruct
(
info: &windows_sys::Win32::Storage::FileSystem::BY_HANDLE_FILE_INFORMATION,
reparse_tag: u32,
basic_info: Option<&windows_sys::Win32::Storage::FileSystem::FILE_BASIC_INFO>,
id_info:
| 136 | /// Ported from _Py_attribute_data_to_stat (fileutils.c) |
| 137 | /// Converts BY_HANDLE_FILE_INFORMATION to StatStruct |
| 138 | fn attribute_data_to_stat( |
| 139 | info: &windows_sys::Win32::Storage::FileSystem::BY_HANDLE_FILE_INFORMATION, |
| 140 | reparse_tag: u32, |
| 141 | basic_info: Option<&windows_sys::Win32::Storage::FileSystem::FILE_BASIC_INFO>, |
| 142 | id_info: Option<&windows_sys::Win32::Storage::FileSystem::FILE_ID_INFO>, |
| 143 | ) -> StatStruct { |
| 144 | use crate::common::fileutils::windows::SECS_BETWEEN_EPOCHS; |
| 145 | use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT; |
| 146 | |
| 147 | let mut st_mode = attributes_to_mode(info.dwFileAttributes); |
| 148 | let st_size = ((info.nFileSizeHigh as u64) << 32) | (info.nFileSizeLow as u64); |
| 149 | let st_dev = id_info |
| 150 | .map(|id| id.VolumeSerialNumber as u32) |
| 151 | .unwrap_or(info.dwVolumeSerialNumber); |
| 152 | let st_nlink = info.nNumberOfLinks as i32; |
| 153 | |
| 154 | // Convert FILETIME/LARGE_INTEGER to (time_t, nsec) |
| 155 | let filetime_to_time = |ft_low: u32, ft_high: u32| -> (libc::time_t, i32) { |
| 156 | let ticks = ((ft_high as i64) << 32) | (ft_low as i64); |
| 157 | let nsec = ((ticks % 10_000_000) * 100) as i32; |
| 158 | let sec = (ticks / 10_000_000 - SECS_BETWEEN_EPOCHS) as libc::time_t; |
| 159 | (sec, nsec) |
| 160 | }; |
| 161 | |
| 162 | let large_integer_to_time = |li: i64| -> (libc::time_t, i32) { |
| 163 | let nsec = ((li % 10_000_000) * 100) as i32; |
| 164 | let sec = (li / 10_000_000 - SECS_BETWEEN_EPOCHS) as libc::time_t; |
| 165 | (sec, nsec) |
| 166 | }; |
| 167 | |
| 168 | let (st_birthtime, st_birthtime_nsec); |
| 169 | let (st_mtime, st_mtime_nsec); |
| 170 | let (st_atime, st_atime_nsec); |
| 171 | |
| 172 | if let Some(bi) = basic_info { |
| 173 | (st_birthtime, st_birthtime_nsec) = large_integer_to_time(bi.CreationTime); |
| 174 | (st_mtime, st_mtime_nsec) = large_integer_to_time(bi.LastWriteTime); |
| 175 | (st_atime, st_atime_nsec) = large_integer_to_time(bi.LastAccessTime); |
| 176 | } else { |
| 177 | (st_birthtime, st_birthtime_nsec) = filetime_to_time( |
| 178 | info.ftCreationTime.dwLowDateTime, |
| 179 | info.ftCreationTime.dwHighDateTime, |
| 180 | ); |
| 181 | (st_mtime, st_mtime_nsec) = filetime_to_time( |
| 182 | info.ftLastWriteTime.dwLowDateTime, |
| 183 | info.ftLastWriteTime.dwHighDateTime, |
| 184 | ); |
| 185 | (st_atime, st_atime_nsec) = filetime_to_time( |
| 186 | info.ftLastAccessTime.dwLowDateTime, |
| 187 | info.ftLastAccessTime.dwHighDateTime, |
| 188 | ); |
| 189 | } |
| 190 | |
| 191 | // Get file ID from id_info or fallback to file index |
| 192 | let (st_ino, st_ino_high) = if let Some(id) = id_info { |
| 193 | // FILE_ID_INFO.FileId is FILE_ID_128 which is [u8; 16] |
| 194 | let bytes = id.FileId.Identifier; |
| 195 | let low = u64::from_le_bytes(bytes[0..8].try_into().unwrap()); |
no test coverage detected