simple_fs/safer/
safer_remove_impl.rs

1use crate::SPath;
2use crate::error::{Cause, PathAndCause};
3use crate::safer::{SaferRemoveOptions, support};
4use crate::{Error, Result};
5use std::fs;
6
7/// Safely deletes a directory if it passes safety checks.
8///
9/// Safety checks (based on options):
10/// - If `restrict_to_current_dir` is true, the directory path must be below the current directory
11/// - If `must_contain_any` is set, the path must contain at least one of the specified patterns
12/// - If `must_contain_all` is set, the path must contain all of the specified patterns
13///
14/// Returns Ok(true) if the directory was deleted, Ok(false) if it didn't exist.
15/// Returns an error if safety checks fail or deletion fails.
16pub fn safer_remove_dir<'a>(dir_path: &SPath, options: impl Into<SaferRemoveOptions<'a>>) -> Result<bool> {
17	let options = options.into();
18
19	// If path doesn't exist, just return false
20	if !dir_path.exists() {
21		return Ok(false);
22	}
23
24	let causes = support::check_path_safety_causes(
25		dir_path,
26		options.restrict_to_current_dir,
27		options.must_contain_any,
28		options.must_contain_all,
29	)?;
30
31	if !causes.is_empty() {
32		return Err(Error::DirNotSafeToRemove(PathAndCause {
33			path: dir_path.to_string(),
34			cause: Cause::Custom(format!("Safety check failed: {}", causes.join("; "))),
35		}));
36	}
37
38	// Perform the deletion
39	fs::remove_dir_all(dir_path.as_std_path()).map_err(|e| {
40		Error::DirNotSafeToRemove(PathAndCause {
41			path: dir_path.to_string(),
42			cause: Cause::Io(Box::new(e)),
43		})
44	})?;
45
46	Ok(true)
47}
48
49/// Safely deletes a file if it passes safety checks.
50///
51/// Safety checks (based on options):
52/// - If `restrict_to_current_dir` is true, the file path must be below the current directory
53/// - If `must_contain_any` is set, the path must contain at least one of the specified patterns
54/// - If `must_contain_all` is set, the path must contain all of the specified patterns
55///
56/// Returns Ok(true) if the file was deleted, Ok(false) if it didn't exist.
57/// Returns an error if safety checks fail or deletion fails.
58pub fn safer_remove_file<'a>(file_path: &SPath, options: impl Into<SaferRemoveOptions<'a>>) -> Result<bool> {
59	let options = options.into();
60
61	// If path doesn't exist, just return false
62	if !file_path.exists() {
63		return Ok(false);
64	}
65
66	let causes = support::check_path_safety_causes(
67		file_path,
68		options.restrict_to_current_dir,
69		options.must_contain_any,
70		options.must_contain_all,
71	)?;
72
73	if !causes.is_empty() {
74		return Err(Error::FileNotSafeToRemove(PathAndCause {
75			path: file_path.to_string(),
76			cause: Cause::Custom(format!("Safety check failed: {}", causes.join("; "))),
77		}));
78	}
79
80	// Perform the deletion
81	fs::remove_file(file_path.as_std_path()).map_err(|e| {
82		Error::FileNotSafeToRemove(PathAndCause {
83			path: file_path.to_string(),
84			cause: Cause::Io(Box::new(e)),
85		})
86	})?;
87
88	Ok(true)
89}
90
91// region:    --- Support
92// endregion: --- Support