From e4e519ca2183efe3c198ff18a1ac73a3943f4817 Mon Sep 17 00:00:00 2001 From: dotandev Date: Wed, 28 Jan 2026 23:02:23 +0100 Subject: [PATCH] Add support for checking file permissions and directory existence --- src/config.rs | 8 ++++++ src/validators/file.rs | 59 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/config.rs b/src/config.rs index 9b51a74..4fd60ae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -39,12 +39,20 @@ pub struct FileCheck { pub path: String, #[serde(default = "default_true")] pub required: bool, + #[serde(default = "default_false")] + pub is_directory: bool, + #[serde(default)] + pub permissions: Option, } fn default_true() -> bool { true } +fn default_false() -> bool { + false +} + impl Config { pub fn load>(path: P) -> Result { let content = fs::read_to_string(path.as_ref()) diff --git a/src/validators/file.rs b/src/validators/file.rs index 0896d7c..0c99537 100644 --- a/src/validators/file.rs +++ b/src/validators/file.rs @@ -19,18 +19,65 @@ impl Validator for FileValidator { let path = Path::new(&self.check.path); if path.exists() { - results.push(ValidationResult::success( - format!("{} exists", self.check.path), - )); + let mut item_passed = true; + + if self.check.is_directory { + if path.is_dir() { + results.push(ValidationResult::success( + format!("Directory {} exists", self.check.path), + )); + } else { + item_passed = false; + results.push(ValidationResult::error( + format!("{} exists but is not a directory", self.check.path), + Some(format!("Ensure {} is a directory", self.check.path)), + )); + } + } else { + results.push(ValidationResult::success( + format!("{} exists", self.check.path), + )); + } + + if item_passed { + if let Some(required_perms) = self.check.permissions { + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + if let Ok(metadata) = path.metadata() { + let actual_perms = metadata.permissions().mode() & 0o777; + if actual_perms == required_perms { + results.push(ValidationResult::success( + format!("{} has correct permissions ({:o})", self.check.path, actual_perms), + )); + } else { + results.push(ValidationResult::error( + format!("{} has permissions {:o}, but {:o} is required", + self.check.path, actual_perms, required_perms), + Some(format!("Run 'chmod {:o} {}' to fix", required_perms, self.check.path)), + )); + } + } + } + #[cfg(not(unix))] + { + results.push(ValidationResult::warning( + format!("Permission check skipped for {} (not supported on this platform)", self.check.path), + None, + )); + } + } + } } else { + let item_type = if self.check.is_directory { "Directory" } else { "File" }; if self.check.required { results.push(ValidationResult::error( - format!("{} does not exist", self.check.path), - Some(format!("Create {} file", self.check.path)), + format!("{} {} does not exist", item_type, self.check.path), + Some(format!("Create {} {}", self.check.path, item_type.to_lowercase())), )); } else { results.push(ValidationResult::warning( - format!("{} does not exist (optional)", self.check.path), + format!("{} {} does not exist (optional)", item_type, self.check.path), None, )); }