use std::fs::{File, OpenOptions};
use std::os::windows::fs::OpenOptionsExt;
use std::path::{Path, PathBuf};
use windows_namespace_request_sys::{OpenFile, PreparedPath, prepare};
use windows_sys::Win32::Storage::FileSystem::{
FILE_FLAG_BACKUP_SEMANTICS, FILE_LIST_DIRECTORY, FILE_SHARE_DELETE, FILE_SHARE_READ,
FILE_SHARE_WRITE, OPEN_EXISTING,
};
use wtf_string::Wtf16String;
pub const AUDITED_SHARE: u32 = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
const FILE_COUNT: usize = 24;
pub struct Tree {
root: PathBuf,
}
impl Tree {
pub fn new(label: &str) -> Self {
let root =
std::env::temp_dir().join(format!("wnrs-acceptance-{}-{label}", std::process::id()));
let _ = std::fs::remove_dir_all(&root);
std::fs::create_dir_all(root.join("child")).expect("create the tree");
for index in 0..FILE_COUNT {
std::fs::write(root.join(format!("f{index:02}.t")), b"contents").expect("write a file");
}
Self { root }
}
pub fn root(&self) -> &Path {
&self.root
}
pub fn file(&self, index: usize) -> PathBuf {
self.root.join(format!("f{index:02}.t"))
}
}
impl Drop for Tree {
fn drop(&mut self) {
let _ = std::fs::remove_dir_all(&self.root);
}
}
pub fn prepared(path: &Path) -> PreparedPath {
let text = path.to_str().expect("the tree's paths are valid UTF-8");
prepare(&Wtf16String::from(text)).expect("prepare the path")
}
pub fn audited_directory_open(path: &Path) -> OpenFile {
OpenFile::new(prepared(path))
.with_desired_access(FILE_LIST_DIRECTORY)
.with_share_mode(AUDITED_SHARE)
.with_creation_disposition(OPEN_EXISTING)
.with_flags_and_attributes(FILE_FLAG_BACKUP_SEMANTICS)
}
pub fn open_directory(path: &Path) -> File {
OpenOptions::new()
.read(true)
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
.open(path)
.expect("open a directory")
}