use prometeu_system::fs::{FsBackend, FsEntry, FsError}; use std::fs; use std::path::PathBuf; pub struct HostDirBackend { root: PathBuf, } impl HostDirBackend { pub fn new(root: impl Into) -> Self { Self { root: root.into() } } fn resolve(&self, path: &str) -> PathBuf { let path = path.trim_start_matches('/'); self.root.join(path) } } impl FsBackend for HostDirBackend { fn mount(&mut self) -> Result<(), FsError> { if !self.root.exists() { return Err(FsError::NotFound); } for dir in &["system", "apps", "media", "user"] { let path = self.root.join(dir); if !path.exists() { fs::create_dir_all(&path).map_err(|e| FsError::IOError(e.to_string()))?; } } Ok(()) } fn unmount(&mut self) {} fn list_dir(&self, path: &str) -> Result, FsError> { let full_path = self.resolve(path); let entries = fs::read_dir(full_path).map_err(|e| FsError::IOError(e.to_string()))?; let mut result = Vec::new(); for entry in entries { let entry = entry.map_err(|e| FsError::IOError(e.to_string()))?; let metadata = entry.metadata().map_err(|e| FsError::IOError(e.to_string()))?; result.push(FsEntry { name: entry.file_name().to_string_lossy().into_owned(), is_dir: metadata.is_dir(), size: metadata.len(), }); } Ok(result) } fn read_file(&self, path: &str) -> Result, FsError> { let full_path = self.resolve(path); fs::read(full_path).map_err(|e| match e.kind() { std::io::ErrorKind::NotFound => FsError::NotFound, _ => FsError::IOError(e.to_string()), }) } fn write_file(&mut self, path: &str, data: &[u8]) -> Result<(), FsError> { let full_path = self.resolve(path); if let Some(parent) = full_path.parent() { fs::create_dir_all(parent).map_err(|e| FsError::IOError(e.to_string()))?; } fs::write(full_path, data).map_err(|e| FsError::IOError(e.to_string())) } fn delete(&mut self, path: &str) -> Result<(), FsError> { let full_path = self.resolve(path); if full_path.is_dir() { fs::remove_dir_all(full_path).map_err(|e| FsError::IOError(e.to_string())) } else { fs::remove_file(full_path).map_err(|e| FsError::IOError(e.to_string())) } } fn exists(&self, path: &str) -> bool { self.resolve(path).exists() } } #[cfg(test)] mod tests { use super::*; use std::env; use std::fs; fn get_temp_dir(name: &str) -> PathBuf { let mut path = env::temp_dir(); path.push(format!( "prometeu_host_test_{}_{}", name, std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_nanos() )); fs::create_dir_all(&path).unwrap(); path } #[test] fn test_host_dir_backend_mount_and_dirs() { let root = get_temp_dir("mount"); let mut backend = HostDirBackend::new(root.clone()); backend.mount().unwrap(); assert!(root.join("system").is_dir()); assert!(root.join("apps").is_dir()); assert!(root.join("media").is_dir()); assert!(root.join("user").is_dir()); let _ = fs::remove_dir_all(root); } }