kaish_kernel/vfs/
builtin_fs.rs1use std::io;
17use std::path::{Path, PathBuf};
18use std::sync::Arc;
19
20use async_trait::async_trait;
21
22use crate::tools::ToolRegistry;
23use super::{DirEntry, Filesystem};
24
25pub struct BuiltinFs {
28 tools: Arc<ToolRegistry>,
29}
30
31impl BuiltinFs {
32 pub fn new(tools: Arc<ToolRegistry>) -> Self {
33 Self { tools }
34 }
35}
36
37#[async_trait]
38impl Filesystem for BuiltinFs {
39 async fn read(&self, path: &Path) -> io::Result<Vec<u8>> {
40 let name = path.to_str().unwrap_or("");
41 if self.tools.get(name).is_some() {
42 Ok(format!("#!/v/bin — kaish builtin: {}\n", name).into_bytes())
43 } else {
44 Err(io::Error::new(io::ErrorKind::NotFound, "builtin not found"))
45 }
46 }
47
48 async fn write(&self, _path: &Path, _data: &[u8]) -> io::Result<()> {
49 Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
50 }
51
52 async fn list(&self, path: &Path) -> io::Result<Vec<DirEntry>> {
53 let p = path.to_str().unwrap_or("");
54 if !p.is_empty() && p != "." {
55 return Err(io::Error::new(io::ErrorKind::NotFound, "not a directory"));
56 }
57 let mut entries: Vec<DirEntry> = self.tools.names().iter().map(|name| {
58 DirEntry::file(name.to_string(), 0)
59 }).collect();
60 entries.sort_by(|a, b| a.name.cmp(&b.name));
61 Ok(entries)
62 }
63
64 async fn stat(&self, path: &Path) -> io::Result<DirEntry> {
65 let name = path.to_str().unwrap_or("");
66 if name.is_empty() || name == "." {
67 return Ok(DirEntry::directory("."));
68 }
69 if self.tools.get(name).is_some() {
70 Ok(DirEntry::file(name, 0))
71 } else {
72 Err(io::Error::new(io::ErrorKind::NotFound, "builtin not found"))
73 }
74 }
75
76 async fn mkdir(&self, _path: &Path) -> io::Result<()> {
77 Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
78 }
79
80 async fn remove(&self, _path: &Path) -> io::Result<()> {
81 Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
82 }
83
84 fn read_only(&self) -> bool {
85 true
86 }
87
88 fn real_path(&self, _path: &Path) -> Option<PathBuf> {
89 None
90 }
91}