use anyhow::{Context, Result}; use std::path::PathBuf; impl crate::sftp::config::SftpConfig { pub fn validate(&self) -> Result<()> { // SFTP section validation if self.sftp.port == 0 { return Err(anyhow::anyhow!("SFTP port cannot be 0")); } if self.sftp.port < 1024 && self.sftp.port != 22 { return Err(anyhow::anyhow!( "SFTP port {} is invalid. Must be >= 1024 or 22 (standard SSH port)", self.sftp.port )); } if self.sftp.base_path.is_empty() { return Err(anyhow::anyhow!("SFTP base_path cannot be empty")); } if self.sftp.auth_db_path.is_empty() { return Err(anyhow::anyhow!("SFTP auth_db_path cannot be empty")); } if self.sftp.max_connections == 0 { return Err(anyhow::anyhow!("SFTP max_connections must be >= 1")); } // Performance section validation if self.performance.path_cache_size == 0 { return Err(anyhow::anyhow!("performance.path_cache_size must be >= 1")); } if self.performance.chunk_size == 0 { return Err(anyhow::anyhow!("performance.chunk_size must be >= 1")); } if self.performance.chunk_size > 1048576 { return Err(anyhow::anyhow!( "performance.chunk_size {} is too large. Max: 1048576 (1MB)", self.performance.chunk_size )); } if self.performance.connection_pool_size == 0 { return Err(anyhow::anyhow!("performance.connection_pool_size must be >= 1")); } if self.performance.max_open_files == 0 { return Err(anyhow::anyhow!("performance.max_open_files must be >= 1")); } if self.performance.max_open_dirs == 0 { return Err(anyhow::anyhow!("performance.max_open_dirs must be >= 1")); } // Resource section validation if self.resource.file_timeout_seconds == 0 { return Err(anyhow::anyhow!("resource.file_timeout_seconds must be >= 1")); } if self.resource.dir_timeout_seconds == 0 { return Err(anyhow::anyhow!("resource.dir_timeout_seconds must be >= 1")); } if self.resource.cleanup_interval_seconds == 0 { return Err(anyhow::anyhow!("resource.cleanup_interval_seconds must be >= 1")); } // Logging section validation if self.logging.level.is_empty() { return Err(anyhow::anyhow!("logging.level cannot be empty")); } let valid_log_levels = ["trace", "debug", "info", "warn", "error", "off"]; if !valid_log_levels.contains(&self.logging.level.as_str()) { return Err(anyhow::anyhow!( "Invalid logging.level: {}. Must be one of: {}", self.logging.level, valid_log_levels.join(", ") )); } // Rsync section validation (if enabled) if self.rsync.enabled { if self.rsync.block_size == 0 { return Err(anyhow::anyhow!("rsync.block_size must be >= 1 when rsync is enabled")); } if self.rsync.compression_level < 1 || self.rsync.compression_level > 9 { return Err(anyhow::anyhow!( "rsync.compression_level {} is invalid. Must be 1-9", self.rsync.compression_level )); } if self.rsync.protocol_version < 27 || self.rsync.protocol_version > 31 { return Err(anyhow::anyhow!( "rsync.protocol_version {} is invalid. Must be 27-31", self.rsync.protocol_version )); } } Ok(()) } }