use anyhow::Result; use std::path::Path; use std::process::Command; use crate::config::SMBConfig; pub struct SMBManager { config: SMBConfig, } impl SMBManager { pub fn new(config: SMBConfig) -> Self { SMBManager { config } } pub fn check_smb_service() -> Result { let output = Command::new("sharing") .arg("-l") .output()?; let status = String::from_utf8_lossy(&output.stdout); Ok(!status.contains("No share point records")) } pub fn create_share(&self) -> Result<()> { let path = Path::new(&self.config.path); if !path.exists() { return Err(anyhow::anyhow!("Path does not exist: {}", self.config.path)); } eprintln!("Creating SMB share '{}' for path: {}", self.config.share_name, self.config.path); let smb_conf_content = self.config.to_smb_conf(); eprintln!("Generated smb.conf section:\n{}", smb_conf_content); eprintln!("\nTo enable SMB sharing, run:"); eprintln!("sudo sharing -a \"{}\" -S \"{}\"", self.config.path, self.config.share_name); Ok(()) } pub fn remove_share(&self) -> Result<()> { eprintln!("Removing SMB share '{}'...", self.config.share_name); eprintln!("To remove SMB sharing, run:"); eprintln!("sudo sharing -r \"{}\"", self.config.share_name); Ok(()) } pub fn list_shares() -> Result> { let output = Command::new("sharing") .arg("-l") .output()?; let status = String::from_utf8_lossy(&output.stdout); if status.contains("No share point records") { return Ok(vec![]); } let shares: Vec = status .lines() .filter(|line| line.contains("name:")) .map(|line| { line.split(":") .nth(1) .unwrap_or("") .trim() .to_string() }) .collect(); Ok(shares) } pub fn status(&self) -> Result { let service_running = Self::check_smb_service()?; let shares = Self::list_shares()?; Ok(serde_json::json!({ "service_running": service_running, "share_name": self.config.share_name, "path": self.config.path, "existing_shares": shares, "config": self.config, })) } }