winbrew_windows\fs/
mod.rs1use std::fs::{self, OpenOptions};
2use std::io;
3use std::path::Path;
4
5use std::os::windows::fs::OpenOptionsExt;
6
7use windows_sys::Win32::Foundation::{CloseHandle, HANDLE, INVALID_HANDLE_VALUE};
8
9use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_OPEN_REPARSE_POINT;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct PathInfo {
14 pub is_directory: bool,
16 pub is_reparse_point: bool,
18 pub hard_link_count: u32,
20}
21
22pub fn inspect_path(path: &Path) -> io::Result<PathInfo> {
38 use std::mem::MaybeUninit;
39 use std::os::windows::ffi::OsStrExt;
40 use windows_sys::Win32::Storage::FileSystem::{
41 BY_HANDLE_FILE_INFORMATION, CreateFileW, FILE_ATTRIBUTE_DIRECTORY,
42 FILE_ATTRIBUTE_REPARSE_POINT, FILE_FLAG_BACKUP_SEMANTICS, FILE_READ_ATTRIBUTES,
43 FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, GetFileInformationByHandle,
44 OPEN_EXISTING,
45 };
46
47 let mut wide_path: Vec<u16> = path.as_os_str().encode_wide().collect();
48 wide_path.push(0);
49
50 unsafe {
51 let handle = CreateFileW(
52 wide_path.as_ptr(),
53 FILE_READ_ATTRIBUTES,
54 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
55 std::ptr::null(),
56 OPEN_EXISTING,
57 FILE_FLAG_BACKUP_SEMANTICS,
58 std::ptr::null_mut(),
59 );
60
61 if handle == INVALID_HANDLE_VALUE {
62 return Err(io::Error::last_os_error());
63 }
64
65 let _handle_guard = HandleGuard(handle);
66
67 let mut info = MaybeUninit::<BY_HANDLE_FILE_INFORMATION>::uninit();
68 if GetFileInformationByHandle(handle, info.as_mut_ptr()) == 0 {
69 return Err(io::Error::last_os_error());
70 }
71
72 let info = info.assume_init();
73
74 Ok(PathInfo {
75 is_directory: info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0,
76 is_reparse_point: info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT != 0,
77 hard_link_count: info.nNumberOfLinks,
78 })
79 }
80}
81
82pub fn create_extraction_target_file(path: &Path) -> io::Result<fs::File> {
97 OpenOptions::new()
98 .write(true)
99 .create_new(true)
100 .custom_flags(FILE_FLAG_OPEN_REPARSE_POINT)
101 .open(path)
102}
103
104#[deprecated(note = "use create_extraction_target_file")]
105#[doc(hidden)]
106pub fn create_extracted_file(path: &Path) -> io::Result<fs::File> {
107 create_extraction_target_file(path)
108}
109
110struct HandleGuard(HANDLE);
111
112impl Drop for HandleGuard {
113 fn drop(&mut self) {
114 unsafe {
115 let _ = CloseHandle(self.0);
116 }
117 }
118}