kaish_kernel/vfs/
builtin_fs.rs1use 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, EntryType, Filesystem, Metadata};
11
12pub 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| DirEntry {
44 name: name.to_string(),
45 entry_type: EntryType::File,
46 size: 0,
47 symlink_target: None,
48 }).collect();
49 entries.sort_by(|a, b| a.name.cmp(&b.name));
50 Ok(entries)
51 }
52
53 async fn stat(&self, path: &Path) -> io::Result<Metadata> {
54 let name = path.to_str().unwrap_or("");
55 if name.is_empty() || name == "." {
56 return Ok(Metadata {
57 is_dir: true,
58 is_file: false,
59 is_symlink: false,
60 size: 0,
61 modified: None,
62 });
63 }
64 if self.tools.get(name).is_some() {
65 Ok(Metadata {
66 is_dir: false,
67 is_file: true,
68 is_symlink: false,
69 size: 0,
70 modified: None,
71 })
72 } else {
73 Err(io::Error::new(io::ErrorKind::NotFound, "builtin not found"))
74 }
75 }
76
77 async fn mkdir(&self, _path: &Path) -> io::Result<()> {
78 Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
79 }
80
81 async fn remove(&self, _path: &Path) -> io::Result<()> {
82 Err(io::Error::new(io::ErrorKind::PermissionDenied, "/v/bin is read-only"))
83 }
84
85 fn read_only(&self) -> bool {
86 true
87 }
88
89 fn real_path(&self, _path: &Path) -> Option<PathBuf> {
90 None
91 }
92}