use std::ffi::OsStr;
#[cfg(unix)]
mod journal;
#[cfg(unix)]
mod manifest;
#[cfg(unix)]
mod session;
#[cfg(unix)]
mod sweep;
#[cfg(all(test, unix))]
mod test_support;
pub(crate) const CHILD_ENVIRONMENT: &str = "FROE_CLEANUP_FAULT_CHILD";
pub(crate) const CUTPOINT_ENVIRONMENT: &str = "FROE_CLEANUP_FAULT_CUTPOINT";
pub(crate) const MODE_ENVIRONMENT: &str = "FROE_CLEANUP_FAULT_MODE";
#[cfg(unix)]
pub(crate) const CRASH_EXIT_CODE: i32 = 86;
#[cfg(unix)]
pub(crate) const VERIFIED_EXIT_CODE: i32 = 87;
#[cfg(unix)]
pub(crate) const CRASH_MODE: &str = "crash";
pub(crate) const ERROR_MODE: &str = "error";
pub(crate) const SUBSTITUTE_MODE: &str = "substitute";
pub(crate) const ABSENCE_MODE: &str = "absence";
pub(crate) fn is_armed(cutpoint: &str, mode: &str) -> bool {
std::env::var_os(CHILD_ENVIRONMENT).as_deref() == Some(OsStr::new("1"))
&& std::env::var_os(CUTPOINT_ENVIRONMENT).as_deref() == Some(OsStr::new(cutpoint))
&& std::env::var_os(MODE_ENVIRONMENT).as_deref() == Some(OsStr::new(mode))
}
pub(super) fn is_substitution_armed(cutpoint: &str) -> bool {
is_armed(cutpoint, SUBSTITUTE_MODE)
}
pub(super) fn crash_if_armed(cutpoint: &str) {
#[cfg(unix)]
if is_armed(cutpoint, CRASH_MODE) {
unsafe { libc::_exit(CRASH_EXIT_CODE) }
}
#[cfg(not(unix))]
let _ = cutpoint;
}
pub(super) fn fail_if_armed(cutpoint: &str) -> crate::error::Result<()> {
if is_armed(cutpoint, ERROR_MODE) {
return Err(
std::io::Error::other(format!("injected cleanup I/O failure at {cutpoint}")).into(),
);
}
Ok(())
}
pub(super) fn substitute_path_if_armed(
cutpoint: &str,
path: &std::path::Path,
) -> crate::error::Result<()> {
if !is_armed(cutpoint, SUBSTITUTE_MODE) {
return Ok(());
}
let file_name = path
.file_name()
.and_then(std::ffi::OsStr::to_str)
.unwrap_or("staging");
let displaced = path.with_file_name(format!("{file_name}.validated-inode"));
std::fs::rename(path, displaced)?;
std::fs::write(path, b"substituted pathname\n")?;
Ok(())
}
pub(super) fn remove_path_if_armed(
cutpoint: &str,
path: &std::path::Path,
) -> crate::error::Result<()> {
if is_armed(cutpoint, ABSENCE_MODE) {
std::fs::remove_file(path)?;
}
Ok(())
}
pub(super) fn omit_last_if_armed<T>(cutpoint: &str, items: &mut Vec<T>) {
if is_armed(cutpoint, SUBSTITUTE_MODE) {
items.pop();
}
}
pub(super) fn append_missing_journal_line_if_armed(cutpoint: &str, expected: &mut Vec<Vec<u8>>) {
if is_armed(cutpoint, SUBSTITUTE_MODE) {
expected.push(b"froe injected missing retained journal line\n".to_vec());
}
}