1extern crate alloc;
2use crate::drivers::Device;
3use crate::fs::vfs::{FileSystem, Inode, Metadata, VNodeType, VfsError};
4use alloc::{
5 boxed::Box,
6 collections::BTreeMap,
7 string::{String, ToString},
8 sync::Arc,
9 vec::Vec,
10};
11use core::any::Any;
12use spin::RwLock;
13
14pub type ReadCallback = Box<dyn Fn(u64, &mut [u8]) -> Result<usize, VfsError> + Send + Sync>;
15pub type WriteCallback = Box<dyn Fn(u64, &[u8]) -> Result<usize, VfsError> + Send + Sync>;
16
17pub enum KernNodeContent {
18 Dir(RwLock<BTreeMap<String, Arc<KernInode>>>),
20 File {
22 read: Option<ReadCallback>,
23 write: Option<WriteCallback>,
24 size: u64,
25 },
26 Device { device: Arc<Device> },
28}
29
30pub struct KernInode {
32 node_type: VNodeType,
33 content: KernNodeContent,
34}
35
36impl core::fmt::Debug for KernInode {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 f.debug_struct("KernInode")
39 .field("node_type", &self.node_type)
40 .finish()
41 }
42}
43
44impl KernInode {
45 pub fn new_dir() -> Arc<Self> {
47 Arc::new(Self {
48 node_type: VNodeType::Dir,
49 content: KernNodeContent::Dir(RwLock::new(BTreeMap::new())),
50 })
51 }
52
53 pub fn new_file(read: Option<ReadCallback>, write: Option<WriteCallback>) -> Arc<Self> {
55 Arc::new(Self {
56 node_type: VNodeType::File,
57 content: KernNodeContent::File {
58 read,
59 write,
60 size: 0,
61 },
62 })
63 }
64 pub fn new_device(device: Arc<Device>) -> Arc<Self> {
66 Arc::new(Self {
67 node_type: VNodeType::Device,
68 content: KernNodeContent::Device { device },
69 })
70 }
71
72 pub fn add_child(&self, name: &str, child: Arc<KernInode>) -> Result<(), VfsError> {
74 match &self.content {
75 KernNodeContent::Dir(entries) => {
76 let mut map = entries.write();
77 if map.contains_key(name) {
78 return Err(VfsError::AlreadyExists);
79 }
80 map.insert(name.to_string(), child);
81 Ok(())
82 }
83 _ => Err(VfsError::NotADirectory),
84 }
85 }
86}
87
88impl Inode for KernInode {
89 fn metadata(&self) -> Result<Metadata, VfsError> {
90 let size = match &self.content {
91 KernNodeContent::File { size, .. } => *size,
92 _ => 0,
93 };
94 Ok(Metadata {
95 size,
96 permissions: 0o755,
97 uid: 0,
98 gid: 0,
99 ctime: 0,
100 mtime: 0,
101 blocks: 0,
102 nlinks: 1,
103 })
104 }
105
106 fn set_metadata(&self, _metadata: &Metadata) -> Result<(), VfsError> {
107 Err(VfsError::NotImplemented)
108 }
109
110 fn node_type(&self) -> VNodeType {
111 self.node_type
112 }
113
114 fn read_at(&self, offset: u64, buf: &mut [u8]) -> Result<usize, VfsError> {
115 match &self.content {
116 KernNodeContent::File { read, .. } => {
117 if let Some(cb) = read {
118 cb(offset, buf)
119 } else {
120 Err(VfsError::PermissionDenied)
121 }
122 }
123 KernNodeContent::Device { device } => {
124 if let Some(char_dev) = device.as_char_device() {
125 char_dev.read(buf).map_err(VfsError::DeviceError)
126 } else {
127 Err(VfsError::NotImplemented)
128 }
129 }
130 _ => Err(VfsError::NotAFile),
131 }
132 }
133
134 fn write_at(&self, offset: u64, buf: &[u8]) -> Result<usize, VfsError> {
135 match &self.content {
136 KernNodeContent::File { write, .. } => {
137 if let Some(cb) = write {
138 cb(offset, buf)
139 } else {
140 Err(VfsError::PermissionDenied)
141 }
142 }
143 KernNodeContent::Device { device } => {
144 if let Some(char_dev) = device.as_char_device() {
145 char_dev.write(buf).map_err(VfsError::DeviceError)
146 } else {
147 Err(VfsError::NotImplemented)
148 }
149 }
150 _ => Err(VfsError::NotAFile),
151 }
152 }
153
154 fn truncate(&self, _size: u64) -> Result<(), VfsError> {
155 Err(VfsError::NotImplemented)
156 }
157
158 fn sync(&self) -> Result<(), VfsError> {
159 Ok(())
160 }
161
162 fn lookup(&self, name: &str) -> Result<Arc<dyn Inode>, VfsError> {
163 match &self.content {
164 KernNodeContent::Dir(entries) => entries
165 .read()
166 .get(name)
167 .cloned()
168 .map(|n| n as Arc<dyn Inode>)
169 .ok_or(VfsError::NotFound),
170 _ => Err(VfsError::NotADirectory),
171 }
172 }
173
174 fn create(&self, name: &str, typ: VNodeType) -> Result<Arc<dyn Inode>, VfsError> {
175 match &self.content {
176 KernNodeContent::Dir(entries) => {
177 let mut map = entries.write();
178 if map.contains_key(name) {
179 return Err(VfsError::AlreadyExists);
180 }
181
182 let new_inode = match typ {
183 VNodeType::Dir => KernInode::new_dir(),
184 VNodeType::File => KernInode::new_file(None, None),
185 _ => return Err(VfsError::NotImplemented),
186 };
187
188 map.insert(name.to_string(), new_inode.clone());
189 Ok(new_inode)
190 }
191 _ => Err(VfsError::NotADirectory),
192 }
193 }
194
195 fn create_device(&self, name: &str, device: Arc<Device>) -> Result<Arc<dyn Inode>, VfsError> {
196 match &self.content {
197 KernNodeContent::Dir(entries) => {
198 let mut map = entries.write();
199 if map.contains_key(name) {
200 return Err(VfsError::AlreadyExists);
201 }
202
203 let new_inode = KernInode::new_device(device);
204 map.insert(name.to_string(), new_inode.clone());
205 Ok(new_inode)
206 }
207 _ => Err(VfsError::NotADirectory),
208 }
209 }
210
211 fn unlink(&self, name: &str) -> Result<(), VfsError> {
212 match &self.content {
213 KernNodeContent::Dir(entries) => {
214 let mut map = entries.write();
215 if map.remove(name).is_some() {
216 Ok(())
217 } else {
218 Err(VfsError::NotFound)
219 }
220 }
221 _ => Err(VfsError::NotADirectory),
222 }
223 }
224
225 fn list(&self) -> Result<Vec<String>, VfsError> {
226 match &self.content {
227 KernNodeContent::Dir(entries) => Ok(entries.read().keys().cloned().collect()),
228 _ => Err(VfsError::NotADirectory),
229 }
230 }
231
232 fn as_any(&self) -> &dyn Any {
233 self
234 }
235}
236
237pub struct KernFs {
238 root: Arc<KernInode>,
239}
240
241impl Default for KernFs {
242 fn default() -> Self {
243 let root = KernInode::new_dir();
244
245 Self { root }
246 }
247}
248
249impl KernFs {
250 pub fn new() -> Self {
251 Self::default()
252 }
253
254 pub fn root(&self) -> Arc<KernInode> {
255 self.root.clone()
256 }
257}
258
259impl FileSystem for KernFs {
260 fn mount(
261 &self,
262 _device: Option<Arc<Device>>,
263 _args: Option<&[&str]>,
264 ) -> Result<Arc<dyn Inode>, VfsError> {
265 Ok(self.root.clone())
266 }
267
268 fn fs_type(&self) -> &'static str {
269 "kernfs"
270 }
271}
272
273#[cfg(test)]
274mod tests {
275 use super::*;
276 use alloc::vec;
277
278 #[test_case]
279 fn test_mount_creates_root() {
280 let kernfs = KernFs::new();
281 let root = kernfs.mount(None, None).unwrap();
282 assert_eq!(root.node_type(), VNodeType::Dir);
283 }
284
285 #[test_case]
286 fn test_create_file() {
287 let kernfs = KernFs::new();
288 let root = kernfs.mount(None, None).unwrap();
289 let file_inode = root.create("test_file", VNodeType::File).unwrap();
290 assert_eq!(file_inode.node_type(), VNodeType::File);
291 }
292
293 #[test_case]
294 fn test_add_child_and_lookup() {
295 let root = KernInode::new_dir();
296 let child_dir = KernInode::new_dir();
297 root.add_child("child_dir", child_dir.clone()).unwrap();
298
299 let looked_up_child = root.lookup("child_dir").unwrap();
300 assert_eq!(looked_up_child.node_type(), VNodeType::Dir);
301
302 assert_eq!(
304 root.add_child("child_dir", child_dir.clone()).unwrap_err(),
305 VfsError::AlreadyExists
306 );
307 }
308
309 #[test_case]
310 fn test_create_and_lookup_file() {
311 let root = KernInode::new_dir();
312 let file = root.create("test_file", VNodeType::File).unwrap();
313 assert_eq!(file.node_type(), VNodeType::File);
314
315 let looked_up_file = root.lookup("test_file").unwrap();
316 assert_eq!(looked_up_file.node_type(), VNodeType::File);
317 }
318
319 #[test_case]
320 fn test_unlink() {
321 let root = KernInode::new_dir();
322 root.create("file_to_unlink", VNodeType::File).unwrap();
323 root.unlink("file_to_unlink").unwrap();
324 assert_eq!(
325 root.lookup("file_to_unlink").unwrap_err(),
326 VfsError::NotFound
327 );
328 }
329
330 #[test_case]
331 fn test_list_directory() {
332 let root = KernInode::new_dir();
333 root.create("file1", VNodeType::File).unwrap();
334 root.create("dir1", VNodeType::Dir).unwrap();
335
336 let mut entries = root.list().unwrap();
337 entries.sort(); assert_eq!(entries, vec!["dir1".to_string(), "file1".to_string()]);
339 }
340
341 #[test_case]
342 fn test_file_read_write() {
343 let file_content = Arc::new(RwLock::new(Vec::<u8>::new()));
344 let content_for_read = file_content.clone();
345 let read_callback: ReadCallback = Box::new(move |offset, buf| {
346 let data = content_for_read.read();
347 let end = (offset + buf.len() as u64).min(data.len() as u64);
348 let start = offset.min(data.len() as u64);
349 let bytes_to_read = (end - start) as usize;
350 buf[..bytes_to_read].copy_from_slice(&data[start as usize..end as usize]);
351 Ok(bytes_to_read)
352 });
353
354 let content_for_write = file_content.clone();
355 let write_callback: WriteCallback = Box::new(move |offset, buf| {
356 let mut data = content_for_write.write();
357 if offset + buf.len() as u64 > data.len() as u64 {
358 data.resize((offset + buf.len() as u64) as usize, 0);
359 }
360 data[offset as usize..(offset + buf.len() as u64) as usize].copy_from_slice(buf);
361 Ok(buf.len())
362 });
363
364 let file_inode = KernInode::new_file(Some(read_callback), Some(write_callback));
365
366 let write_data = b"hello world";
368 file_inode.write_at(0, write_data).unwrap();
369
370 let mut read_buffer = vec![0; write_data.len()];
372 file_inode.read_at(0, &mut read_buffer).unwrap();
373 assert_eq!(read_buffer, write_data);
374
375 let mut partial_read_buffer = vec![0; 5];
377 file_inode.read_at(0, &mut partial_read_buffer).unwrap();
378 assert_eq!(partial_read_buffer, b"hello");
379
380 file_inode.read_at(6, &mut partial_read_buffer).unwrap();
381 assert_eq!(partial_read_buffer, b"world");
382
383 file_inode.write_at(6, b"rust").unwrap();
385 let mut full_read_buffer = vec![0; 10];
386 file_inode.read_at(0, &mut full_read_buffer).unwrap();
387 assert_eq!(full_read_buffer, b"hello rust");
388
389 let no_perm_file = KernInode::new_file(None, None);
391 assert_eq!(
392 no_perm_file.read_at(0, &mut [0]).unwrap_err(),
393 VfsError::PermissionDenied
394 );
395 assert_eq!(
396 no_perm_file.write_at(0, &[0]).unwrap_err(),
397 VfsError::PermissionDenied
398 );
399 }
400
401 #[test_case]
402 fn test_error_scenarios() {
403 let root = KernInode::new_dir();
404 let file_inode = KernInode::new_file(None, None);
405
406 assert_eq!(
408 file_inode
409 .add_child("child", KernInode::new_dir())
410 .unwrap_err(),
411 VfsError::NotADirectory
412 );
413 assert_eq!(
414 file_inode.lookup("child").unwrap_err(),
415 VfsError::NotADirectory
416 );
417 assert_eq!(
418 file_inode.create("child", VNodeType::File).unwrap_err(),
419 VfsError::NotADirectory
420 );
421 assert_eq!(
422 file_inode
423 .create_device("child", Arc::new(Device::null()))
424 .unwrap_err(),
425 VfsError::NotADirectory
426 );
427 assert_eq!(
428 file_inode.unlink("child").unwrap_err(),
429 VfsError::NotADirectory
430 );
431 assert_eq!(file_inode.list().unwrap_err(), VfsError::NotADirectory);
432
433 assert_eq!(root.read_at(0, &mut [0]).unwrap_err(), VfsError::NotAFile);
435 assert_eq!(root.write_at(0, &[0]).unwrap_err(), VfsError::NotAFile);
436
437 assert_eq!(
443 root.create("symlink", VNodeType::SymLink).unwrap_err(),
444 VfsError::NotImplemented
445 );
446
447 assert_eq!(
449 root.set_metadata(&Metadata::default()).unwrap_err(),
450 VfsError::NotImplemented
451 );
452 assert_eq!(
454 file_inode.truncate(0).unwrap_err(),
455 VfsError::NotImplemented
456 );
457 }
458
459 struct MockCharDevice {
461 data: RwLock<Vec<u8>>,
462 name: String,
463 }
464
465 impl crate::drivers::SharedDeviceOps for MockCharDevice {
466 fn name(&self) -> &str {
467 &self.name
468 }
469 fn device_type(&self) -> crate::drivers::DeviceType {
470 crate::drivers::DeviceType::Char
471 }
472 fn open(&self) -> Result<(), crate::drivers::DeviceError> {
473 Ok(())
474 }
475 fn close(&self) -> Result<(), crate::drivers::DeviceError> {
476 Ok(())
477 }
478 fn ioctl(&self, _cmd: u64, _arg: u64) -> Result<u64, crate::drivers::DeviceError> {
479 Err(crate::drivers::DeviceError::NotSupported)
480 }
481 }
482
483 impl crate::drivers::CharDevice for MockCharDevice {
484 fn read(&self, buf: &mut [u8]) -> Result<usize, crate::drivers::DeviceError> {
485 let mut data = self.data.write();
486 let bytes_to_read = buf.len().min(data.len());
487 buf[..bytes_to_read].copy_from_slice(&data[..bytes_to_read]);
488 data.drain(..bytes_to_read);
489 Ok(bytes_to_read)
490 }
491
492 fn write(&self, buf: &[u8]) -> Result<usize, crate::drivers::DeviceError> {
493 self.data.write().extend_from_slice(buf);
494 Ok(buf.len())
495 }
496 }
497
498 impl MockCharDevice {
499 fn new(name: &str, initial_data: &[u8]) -> Arc<Self> {
500 Arc::new(Self {
501 data: RwLock::new(initial_data.to_vec()),
502 name: name.to_string(),
503 })
504 }
505 }
506
507 struct MockBlockDevice {
509 name: String,
510 block_size: usize,
511 num_blocks: usize,
512 data: RwLock<Vec<u8>>,
513 }
514
515 impl crate::drivers::SharedDeviceOps for MockBlockDevice {
516 fn name(&self) -> &str {
517 &self.name
518 }
519 fn device_type(&self) -> crate::drivers::DeviceType {
520 crate::drivers::DeviceType::Block
521 }
522 fn open(&self) -> Result<(), crate::drivers::DeviceError> {
523 Ok(())
524 }
525 fn close(&self) -> Result<(), crate::drivers::DeviceError> {
526 Ok(())
527 }
528 fn ioctl(&self, _cmd: u64, _arg: u64) -> Result<u64, crate::drivers::DeviceError> {
529 Err(crate::drivers::DeviceError::NotSupported)
530 }
531 }
532
533 impl crate::drivers::BlockDevice for MockBlockDevice {
534 fn block_size(&self) -> usize {
535 self.block_size
536 }
537 fn num_blocks(&self) -> usize {
538 self.num_blocks
539 }
540
541 fn read_blocks(
542 &self,
543 block_idx: usize,
544 num_blocks: usize,
545 buf: &mut [u8],
546 ) -> Result<usize, crate::drivers::DeviceError> {
547 let start_byte = block_idx * self.block_size;
548 let end_byte = (block_idx + num_blocks) * self.block_size;
549 let data = self.data.read();
550
551 if start_byte >= data.len() {
552 return Ok(0);
553 }
554 let bytes_to_read = buf
555 .len()
556 .min(data.len() - start_byte)
557 .min(end_byte - start_byte);
558 buf[..bytes_to_read].copy_from_slice(&data[start_byte..(start_byte + bytes_to_read)]);
559 Ok(bytes_to_read)
560 }
561
562 fn write_blocks(
563 &self,
564 block_idx: usize,
565 num_blocks: usize,
566 buf: &[u8],
567 ) -> Result<usize, crate::drivers::DeviceError> {
568 let start_byte = block_idx * self.block_size;
569 let end_byte = (block_idx + num_blocks) * self.block_size;
570 let mut data = self.data.write();
571
572 if end_byte > data.len() {
573 data.resize(end_byte, 0);
574 }
575 let bytes_to_write = buf.len().min(end_byte - start_byte);
576 data[start_byte..(start_byte + bytes_to_write)]
577 .copy_from_slice(buf[..bytes_to_write].as_ref());
578 Ok(bytes_to_write)
579 }
580 }
581
582 impl MockBlockDevice {
583 fn new(name: &str, block_size: usize, num_blocks: usize, initial_data: &[u8]) -> Arc<Self> {
584 let mut data = initial_data.to_vec();
585 data.resize(block_size * num_blocks, 0);
586 Arc::new(Self {
587 name: name.to_string(),
588 block_size,
589 num_blocks,
590 data: RwLock::new(data),
591 })
592 }
593 }
594
595 #[test_case]
596 fn test_device_node_read_write() {
597 let root = KernInode::new_dir();
598 let mock_char_device = MockCharDevice::new("test_char_dev", b"device_data");
599 let char_device_arc = Arc::new(crate::drivers::Device::new_auto_assign(
600 "test_char_dev".to_string(),
601 crate::drivers::DeviceInner::Char(mock_char_device.clone()),
602 ));
603
604 let device_inode = root
605 .create_device("test_device", char_device_arc.clone())
606 .unwrap();
607 assert_eq!(device_inode.node_type(), VNodeType::Device);
608
609 let mut read_buffer = vec![0; 5];
611 device_inode.read_at(0, &mut read_buffer).unwrap();
612 assert_eq!(read_buffer, b"devic"); let write_mock_device = MockCharDevice::new("write_char_dev", b"");
616 let write_device_arc = Arc::new(crate::drivers::Device::new_auto_assign(
617 "write_char_dev".to_string(),
618 crate::drivers::DeviceInner::Char(write_mock_device.clone()),
619 ));
620 let write_device_inode = root
621 .create_device("write_test_device", write_device_arc)
622 .unwrap();
623
624 write_device_inode.write_at(0, b"write_test").unwrap();
625 let mut fresh_read_buffer = vec![0; 10];
626 write_device_inode
627 .read_at(0, &mut fresh_read_buffer)
628 .unwrap();
629 assert_eq!(fresh_read_buffer, b"write_test");
630
631 let mock_block_device =
633 MockBlockDevice::new("test_block_dev", 512, 10, b"initial_block_data");
634 let block_device_arc = Arc::new(crate::drivers::Device::new_auto_assign(
635 "test_block_dev".to_string(),
636 crate::drivers::DeviceInner::Block(mock_block_device.clone()),
637 ));
638 let block_device_inode = root.create_device("block_dev", block_device_arc).unwrap();
639 assert_eq!(
640 block_device_inode.read_at(0, &mut [0]).unwrap_err(),
641 VfsError::NotImplemented
642 );
643
644 let null_device_arc = Arc::new(crate::drivers::Device::null());
646 let null_inode = root
647 .create_device("null_device_node", null_device_arc)
648 .unwrap();
649 let mut null_read_buf = [0; 10];
650 assert_eq!(null_inode.read_at(0, &mut null_read_buf).unwrap(), 0);
651 assert_eq!(null_inode.write_at(0, b"data").unwrap(), 4);
652 }
653}