use crate::host::{Access, Private};
use crate::service::Permit;
use std::fs::File;
use std::io;
use std::path::Path;
use std::time::SystemTime;
fn not_yet() -> io::Error {
io::Error::new(
io::ErrorKind::Unsupported,
"Pitboard does not change files on Windows yet",
)
}
pub(crate) fn create_private_dir(_: Permit, _path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn create_private(_: Permit, _path: &Path) -> io::Result<File> {
Err(not_yet())
}
pub(crate) fn open_private_append(_: Permit, _path: &Path) -> io::Result<File> {
Err(not_yet())
}
pub(crate) fn open_private_lock(_: Permit, _path: &Path) -> io::Result<File> {
Err(not_yet())
}
pub(crate) fn copy_access(_: Permit, _existing: &Path, _temp: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn sync_dir(_dir: &Path) {}
pub(crate) fn touch_dir(_: Permit, _path: &Path, _at: SystemTime) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn create_dir_all(_: Permit, _path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn create_dir(_: Permit, _path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn copy(_: Permit, _from: &Path, _to: &Path) -> io::Result<u64> {
Err(not_yet())
}
pub(crate) fn rename(_: Permit, _from: &Path, _to: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn remove_file(_: Permit, _path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn remove_dir(_: Permit, _path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn remove_dir_all(_: Permit, _path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn private_dir(_path: &Path) -> io::Result<Private> {
Err(not_yet())
}
pub(crate) fn lock_dir(_path: &Path) -> io::Result<File> {
Err(not_yet())
}
pub(crate) fn move_new(_: Permit, _from: &Path, _to: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn flush_dir(_dir: &Path) -> io::Result<()> {
Err(not_yet())
}
pub(crate) fn same_volume(_a: &Path, _b: &Path) -> io::Result<bool> {
Err(not_yet())
}
#[cfg(any(test, feature = "test-support"))]
pub(crate) fn file_id(_path: &Path) -> Option<(u64, u64)> {
None
}
pub(crate) fn access(_path: &Path) -> Option<Access> {
None
}
#[cfg(any(test, feature = "test-support"))]
#[cfg_attr(not(feature = "test-support"), allow(unreachable_pub))]
pub mod testing {
use std::io;
use std::path::Path;
fn not_yet() -> io::Error {
io::Error::new(
io::ErrorKind::Unsupported,
"a file's access on Windows is set by W15",
)
}
pub fn open_to_others(_path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn make_private(_path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn is_private(_path: &Path) -> io::Result<bool> {
Err(not_yet())
}
pub fn read_only_for_owner(_path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn deny_reading(_path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn make_runnable(path: &Path) -> io::Result<()> {
std::fs::metadata(path).map(drop)
}
pub fn deny_running(_path: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn deny_changes(_dir: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn allow_changes(_dir: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn link(_target: &Path, _at: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn link_dir(_target: &Path, _at: &Path) -> io::Result<()> {
Err(not_yet())
}
pub fn inode(_path: &Path) -> io::Result<u64> {
Err(not_yet())
}
}
#[cfg(test)]
mod tests {
use super::testing;
use std::io;
use std::path::Path;
#[test]
fn every_change_to_a_files_access_waits_for_w15() {
let path = Path::new("never-made");
let answers: [(&str, io::Result<()>); 10] = [
("open_to_others", testing::open_to_others(path)),
("make_private", testing::make_private(path)),
("read_only_for_owner", testing::read_only_for_owner(path)),
("deny_reading", testing::deny_reading(path)),
("deny_running", testing::deny_running(path)),
("deny_changes", testing::deny_changes(path)),
("allow_changes", testing::allow_changes(path)),
("link", testing::link(path, path)),
("link_dir", testing::link_dir(path, path)),
("inode", testing::inode(path).map(drop)),
];
for (what, answer) in answers {
let refused = answer.expect_err(what);
assert_eq!(refused.kind(), io::ErrorKind::Unsupported, "{what}");
}
let private = testing::is_private(path).expect_err("is_private");
assert_eq!(private.kind(), io::ErrorKind::Unsupported);
assert!(!path.exists(), "nothing was made");
}
#[test]
fn a_file_a_test_wrote_is_runnable_as_it_is() {
let dir = std::env::temp_dir().join(format!("pitboard-runnable-{}", std::process::id()));
std::fs::create_dir_all(&dir).expect("a scratch folder");
let program = dir.join("program.exe");
std::fs::copy(std::env::current_exe().expect("this test"), &program).expect("copied");
let before = std::fs::read(&program).expect("read");
testing::make_runnable(&program).expect("runnable as it is");
assert_eq!(std::fs::read(&program).expect("read"), before, "unchanged");
let missing = testing::make_runnable(&dir.join("absent.exe")).expect_err("absent");
assert_eq!(missing.kind(), io::ErrorKind::NotFound);
let ran = std::process::Command::new(&program)
.args(["--list", "--format=terse"])
.output()
.expect("the copy runs");
assert!(ran.status.success(), "{ran:?}");
let _ = std::fs::remove_dir_all(&dir);
}
}