Skip to main content

kaish_kernel/vfs/
builtin_fs.rs

1//! BuiltinFs — read-only VFS that presents builtins as executable entries under `/v/bin/`.
2
3use std::io;
4use std::path::{Path, PathBuf};
5use std::sync::Arc;
6
7use async_trait::async_trait;
8
9use crate::tools::ToolRegistry;
10use super::traits::{DirEntry, Filesystem};
11
12/// A read-only filesystem that exposes registered builtins as entries.
13pub struct BuiltinFs {
14    tools: Arc<ToolRegistry>,
15}
16
17impl BuiltinFs {
18    pub fn new(tools: Arc<ToolRegistry>) -> Self {
19        Self { tools }
20    }
21}
22
23#[async_trait]
24impl Filesystem for BuiltinFs {
25    async fn read(&self, path: &Path) -> io::Result<Vec<u8>> {
26        let name = path.to_str().unwrap_or("");
27        if self.tools.get(name).is_some() {
28            Ok(format!("#!/v/bin — kaish builtin: {}\n", name).into_bytes())
29        } else {
30            Err(io::Error::new(io::ErrorKind::NotFound, "builtin not found"))
31        }
32    }
33
34    async fn write(&self, _path: &Path, _data: &[u8]) -> io::Result<()> {
35        Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
36    }
37
38    async fn list(&self, path: &Path) -> io::Result<Vec<DirEntry>> {
39        let p = path.to_str().unwrap_or("");
40        if !p.is_empty() && p != "." {
41            return Err(io::Error::new(io::ErrorKind::NotFound, "not a directory"));
42        }
43        let mut entries: Vec<DirEntry> = self.tools.names().iter().map(|name| {
44            DirEntry::file(name.to_string(), 0)
45        }).collect();
46        entries.sort_by(|a, b| a.name.cmp(&b.name));
47        Ok(entries)
48    }
49
50    async fn stat(&self, path: &Path) -> io::Result<DirEntry> {
51        let name = path.to_str().unwrap_or("");
52        if name.is_empty() || name == "." {
53            return Ok(DirEntry::directory("."));
54        }
55        if self.tools.get(name).is_some() {
56            Ok(DirEntry::file(name, 0))
57        } else {
58            Err(io::Error::new(io::ErrorKind::NotFound, "builtin not found"))
59        }
60    }
61
62    async fn mkdir(&self, _path: &Path) -> io::Result<()> {
63        Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
64    }
65
66    async fn remove(&self, _path: &Path) -> io::Result<()> {
67        Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
68    }
69
70    fn read_only(&self) -> bool {
71        true
72    }
73
74    fn real_path(&self, _path: &Path) -> Option<PathBuf> {
75        None
76    }
77}