1use alloc::{collections::BTreeMap, string::String, sync::Arc, vec, vec::Vec};
6
7#[cfg(not(target_arch = "aarch64"))]
8use spin::RwLock;
9
10#[cfg(target_arch = "aarch64")]
11use super::bare_lock::RwLock;
12use super::{DirEntry, Filesystem, Metadata, NodeType, Permissions, VfsNode};
13use crate::error::{FsError, KernelError};
14
15struct RamNode {
17 node_type: NodeType,
19
20 data: RwLock<Vec<u8>>,
22
23 children: RwLock<BTreeMap<String, Arc<RamNode>>>,
25
26 metadata: RwLock<Metadata>,
28
29 inode: u64,
31
32 parent_inode: u64,
34}
35
36impl RamNode {
37 fn new_file(inode: u64, parent_inode: u64, permissions: Permissions) -> Self {
39 Self {
40 node_type: NodeType::File,
41 data: RwLock::new(Vec::new()),
42 children: RwLock::new(BTreeMap::new()),
43 metadata: RwLock::new(Metadata {
44 node_type: NodeType::File,
45 size: 0,
46 permissions,
47 uid: 0,
48 gid: 0,
49 created: crate::arch::timer::get_timestamp_secs(),
50 modified: crate::arch::timer::get_timestamp_secs(),
51 accessed: crate::arch::timer::get_timestamp_secs(),
52 inode,
53 }),
54 inode,
55 parent_inode,
56 }
57 }
58
59 fn new_directory(inode: u64, parent_inode: u64, permissions: Permissions) -> Self {
61 Self {
62 node_type: NodeType::Directory,
63 data: RwLock::new(Vec::new()),
64 children: RwLock::new(BTreeMap::new()),
65 metadata: RwLock::new(Metadata {
66 node_type: NodeType::Directory,
67 size: 0,
68 permissions,
69 uid: 0,
70 gid: 0,
71 created: crate::arch::timer::get_timestamp_secs(),
72 modified: crate::arch::timer::get_timestamp_secs(),
73 accessed: crate::arch::timer::get_timestamp_secs(),
74 inode,
75 }),
76 inode,
77 parent_inode,
78 }
79 }
80
81 fn new_symlink(inode: u64, parent_inode: u64, target: &str) -> Self {
85 let target_bytes = Vec::from(target.as_bytes());
86 let size = target_bytes.len();
87 Self {
88 node_type: NodeType::Symlink,
89 data: RwLock::new(target_bytes),
90 children: RwLock::new(BTreeMap::new()),
91 metadata: RwLock::new(Metadata {
92 node_type: NodeType::Symlink,
93 size,
94 permissions: Permissions::from_mode(0o777),
95 uid: 0,
96 gid: 0,
97 created: crate::arch::timer::get_timestamp_secs(),
98 modified: crate::arch::timer::get_timestamp_secs(),
99 accessed: crate::arch::timer::get_timestamp_secs(),
100 inode,
101 }),
102 inode,
103 parent_inode,
104 }
105 }
106}
107
108impl VfsNode for RamNode {
109 fn node_type(&self) -> NodeType {
110 self.node_type
111 }
112
113 fn read(&self, offset: usize, buffer: &mut [u8]) -> Result<usize, crate::error::KernelError> {
114 if self.node_type != NodeType::File {
115 return Err(KernelError::FsError(FsError::NotAFile));
116 }
117
118 let data = self.data.read();
119 if offset >= data.len() {
120 return Ok(0);
121 }
122
123 let bytes_to_read = core::cmp::min(buffer.len(), data.len() - offset);
124 buffer[..bytes_to_read].copy_from_slice(&data[offset..offset + bytes_to_read]);
125
126 self.metadata.write().accessed = crate::arch::timer::get_timestamp_secs();
128
129 Ok(bytes_to_read)
130 }
131
132 fn write(&self, offset: usize, data: &[u8]) -> Result<usize, crate::error::KernelError> {
133 if self.node_type != NodeType::File {
134 return Err(KernelError::FsError(FsError::NotAFile));
135 }
136
137 let mut file_data = self.data.write();
138
139 if offset > file_data.len() {
141 file_data.resize(offset, 0);
142 }
143
144 if offset + data.len() > file_data.len() {
146 file_data.resize(offset + data.len(), 0);
147 }
148 file_data[offset..offset + data.len()].copy_from_slice(data);
149
150 let mut metadata = self.metadata.write();
152 metadata.size = file_data.len();
153 metadata.modified = crate::arch::timer::get_timestamp_secs();
154
155 Ok(data.len())
156 }
157
158 fn metadata(&self) -> Result<Metadata, crate::error::KernelError> {
159 Ok(self.metadata.read().clone())
160 }
161
162 fn readdir(&self) -> Result<Vec<DirEntry>, crate::error::KernelError> {
163 if self.node_type != NodeType::Directory {
164 return Err(KernelError::FsError(FsError::NotADirectory));
165 }
166
167 let children = self.children.read();
168 let mut entries = Vec::new();
169
170 entries.push(DirEntry {
172 name: String::from("."),
173 node_type: NodeType::Directory,
174 inode: self.inode,
175 });
176
177 entries.push(DirEntry {
178 name: String::from(".."),
179 node_type: NodeType::Directory,
180 inode: self.parent_inode,
181 });
182
183 for (name, child) in children.iter() {
185 entries.push(DirEntry {
186 name: name.clone(),
187 node_type: child.node_type,
188 inode: child.inode,
189 });
190 }
191
192 Ok(entries)
193 }
194
195 fn lookup(&self, name: &str) -> Result<Arc<dyn VfsNode>, crate::error::KernelError> {
196 if self.node_type != NodeType::Directory {
197 return Err(KernelError::FsError(FsError::NotADirectory));
198 }
199
200 let children = self.children.read();
201 children
202 .get(name)
203 .map(|node| node.clone() as Arc<dyn VfsNode>)
204 .ok_or(KernelError::FsError(FsError::NotFound))
205 }
206
207 fn create(
208 &self,
209 name: &str,
210 permissions: Permissions,
211 ) -> Result<Arc<dyn VfsNode>, crate::error::KernelError> {
212 if self.node_type != NodeType::Directory {
213 return Err(KernelError::FsError(FsError::NotADirectory));
214 }
215
216 let mut children = self.children.write();
217
218 if children.contains_key(name) {
219 return Err(KernelError::FsError(FsError::AlreadyExists));
220 }
221
222 let inode = NEXT_INODE.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
223 let new_file = Arc::new(RamNode::new_file(inode, self.inode, permissions));
224 children.insert(String::from(name), new_file.clone());
225
226 Ok(new_file as Arc<dyn VfsNode>)
227 }
228
229 fn mkdir(
230 &self,
231 name: &str,
232 permissions: Permissions,
233 ) -> Result<Arc<dyn VfsNode>, crate::error::KernelError> {
234 if self.node_type != NodeType::Directory {
235 return Err(KernelError::FsError(FsError::NotADirectory));
236 }
237
238 let mut children = self.children.write();
239
240 if children.contains_key(name) {
241 return Err(KernelError::FsError(FsError::AlreadyExists));
242 }
243
244 let inode = NEXT_INODE.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
245 let new_dir = Arc::new(RamNode::new_directory(inode, self.inode, permissions));
246 children.insert(String::from(name), new_dir.clone());
247
248 Ok(new_dir as Arc<dyn VfsNode>)
249 }
250
251 fn unlink(&self, name: &str) -> Result<(), crate::error::KernelError> {
252 if self.node_type != NodeType::Directory {
253 return Err(KernelError::FsError(FsError::NotADirectory));
254 }
255
256 let mut children = self.children.write();
257
258 if let Some(node) = children.get(name) {
259 if node.node_type == NodeType::Directory {
260 let dir_children = node.children.read();
262 if !dir_children.is_empty() {
263 return Err(KernelError::FsError(FsError::DirectoryNotEmpty));
264 }
265 }
266
267 children.remove(name);
268 Ok(())
269 } else {
270 Err(KernelError::FsError(FsError::NotFound))
271 }
272 }
273
274 fn truncate(&self, size: usize) -> Result<(), crate::error::KernelError> {
275 if self.node_type != NodeType::File {
276 return Err(KernelError::FsError(FsError::NotAFile));
277 }
278
279 let mut data = self.data.write();
280 data.resize(size, 0);
281
282 let mut metadata = self.metadata.write();
283 metadata.size = size;
284 metadata.modified = crate::arch::timer::get_timestamp_secs();
285
286 Ok(())
287 }
288
289 fn link(&self, name: &str, target: Arc<dyn VfsNode>) -> Result<(), KernelError> {
290 if self.node_type != NodeType::Directory {
291 return Err(KernelError::FsError(FsError::NotADirectory));
292 }
293
294 if target.node_type() == NodeType::Directory {
296 return Err(KernelError::FsError(FsError::IsADirectory));
297 }
298
299 let mut children = self.children.write();
300 if children.contains_key(name) {
301 return Err(KernelError::FsError(FsError::AlreadyExists));
302 }
303
304 let target_meta = target.metadata()?;
310 let inode = target_meta.inode;
311
312 let new_node = Arc::new(RamNode::new_file(
313 inode,
314 self.inode,
315 target_meta.permissions,
316 ));
317
318 let mut buf = vec![0u8; target_meta.size];
320 if !buf.is_empty() {
321 let bytes_read = target.read(0, &mut buf)?;
322 buf.truncate(bytes_read);
323 }
324 if !buf.is_empty() {
325 new_node.write(0, &buf)?;
326 }
327
328 children.insert(String::from(name), new_node);
329 Ok(())
330 }
331
332 fn symlink(&self, name: &str, target: &str) -> Result<Arc<dyn VfsNode>, KernelError> {
333 if self.node_type != NodeType::Directory {
334 return Err(KernelError::FsError(FsError::NotADirectory));
335 }
336
337 let mut children = self.children.write();
338 if children.contains_key(name) {
339 return Err(KernelError::FsError(FsError::AlreadyExists));
340 }
341
342 let inode = NEXT_INODE.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
343 let new_symlink = Arc::new(RamNode::new_symlink(inode, self.inode, target));
344 children.insert(String::from(name), new_symlink.clone());
345
346 Ok(new_symlink as Arc<dyn VfsNode>)
347 }
348
349 fn readlink(&self) -> Result<String, KernelError> {
350 if self.node_type != NodeType::Symlink {
351 return Err(KernelError::FsError(FsError::NotASymlink));
352 }
353
354 let data = self.data.read();
355 let s =
356 core::str::from_utf8(&data).map_err(|_| KernelError::FsError(FsError::InvalidPath))?;
357 Ok(String::from(s))
358 }
359
360 fn chmod(&self, permissions: Permissions) -> Result<(), KernelError> {
361 let mut metadata = self.metadata.write();
362 metadata.permissions = permissions;
363 metadata.modified = crate::arch::timer::get_timestamp_secs();
364 Ok(())
365 }
366}
367
368static NEXT_INODE: core::sync::atomic::AtomicU64 = core::sync::atomic::AtomicU64::new(1);
370
371pub struct RamFs {
373 root: Arc<RamNode>,
374}
375
376impl RamFs {
377 pub fn new() -> Self {
379 let root_inode = NEXT_INODE.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
380 let root = Arc::new(RamNode::new_directory(
382 root_inode,
383 root_inode,
384 Permissions::default(),
385 ));
386
387 Self { root }
388 }
389}
390
391impl Default for RamFs {
392 fn default() -> Self {
393 Self::new()
394 }
395}
396
397impl Filesystem for RamFs {
398 fn root(&self) -> Arc<dyn VfsNode> {
399 self.root.clone() as Arc<dyn VfsNode>
400 }
401
402 fn name(&self) -> &str {
403 "ramfs"
404 }
405
406 fn is_readonly(&self) -> bool {
407 false
408 }
409
410 fn sync(&self) -> Result<(), crate::error::KernelError> {
411 Ok(())
413 }
414}
415
416#[cfg(test)]
417mod tests {
418 use alloc::vec;
419
420 use super::*;
421
422 #[test]
425 fn test_ramfs_new() {
426 let fs = RamFs::new();
427 assert_eq!(fs.name(), "ramfs");
428 assert!(!fs.is_readonly());
429 }
430
431 #[test]
432 fn test_ramfs_default() {
433 let fs = RamFs::default();
434 assert_eq!(fs.name(), "ramfs");
435 }
436
437 #[test]
438 fn test_ramfs_root_is_directory() {
439 let fs = RamFs::new();
440 let root = fs.root();
441 assert_eq!(root.node_type(), NodeType::Directory);
442 }
443
444 #[test]
445 fn test_ramfs_sync() {
446 let fs = RamFs::new();
447 assert!(fs.sync().is_ok());
448 }
449
450 #[test]
453 fn test_create_file() {
454 let fs = RamFs::new();
455 let root = fs.root();
456
457 let file = root.create("hello.txt", Permissions::default());
458 assert!(file.is_ok());
459 assert_eq!(file.unwrap().node_type(), NodeType::File);
460 }
461
462 #[test]
463 fn test_create_duplicate_file_fails() {
464 let fs = RamFs::new();
465 let root = fs.root();
466
467 root.create("dup.txt", Permissions::default()).unwrap();
468 let result = root.create("dup.txt", Permissions::default());
469 assert!(result.is_err());
470 assert_eq!(
471 result.err().expect("expected Err"),
472 KernelError::FsError(FsError::AlreadyExists)
473 );
474 }
475
476 #[test]
477 fn test_write_and_read_file() {
478 let fs = RamFs::new();
479 let root = fs.root();
480
481 let file = root.create("data.txt", Permissions::default()).unwrap();
482
483 let written = file.write(0, b"Hello, World!");
485 assert!(written.is_ok());
486 assert_eq!(written.unwrap(), 13);
487
488 let mut buf = vec![0u8; 20];
490 let read = file.read(0, &mut buf);
491 assert!(read.is_ok());
492 assert_eq!(read.unwrap(), 13);
493 assert_eq!(&buf[..13], b"Hello, World!");
494 }
495
496 #[test]
497 fn test_write_at_offset() {
498 let fs = RamFs::new();
499 let root = fs.root();
500 let file = root.create("offset.txt", Permissions::default()).unwrap();
501
502 file.write(0, b"AAAA").unwrap();
504 file.write(1, b"BB").unwrap();
506
507 let mut buf = vec![0u8; 4];
508 file.read(0, &mut buf).unwrap();
509 assert_eq!(&buf, b"ABBA");
510 }
511
512 #[test]
513 fn test_write_extends_file() {
514 let fs = RamFs::new();
515 let root = fs.root();
516 let file = root.create("extend.txt", Permissions::default()).unwrap();
517
518 file.write(5, b"end").unwrap();
520
521 let mut buf = vec![0u8; 8];
522 let n = file.read(0, &mut buf).unwrap();
523 assert_eq!(n, 8);
524 assert_eq!(&buf[..5], &[0, 0, 0, 0, 0]);
525 assert_eq!(&buf[5..8], b"end");
526 }
527
528 #[test]
529 fn test_read_at_offset_beyond_eof() {
530 let fs = RamFs::new();
531 let root = fs.root();
532 let file = root.create("eof.txt", Permissions::default()).unwrap();
533 file.write(0, b"short").unwrap();
534
535 let mut buf = vec![0u8; 10];
536 let n = file.read(100, &mut buf).unwrap();
537 assert_eq!(n, 0);
538 }
539
540 #[test]
541 fn test_read_partial() {
542 let fs = RamFs::new();
543 let root = fs.root();
544 let file = root.create("partial.txt", Permissions::default()).unwrap();
545 file.write(0, b"Hello, World!").unwrap();
546
547 let mut buf = vec![0u8; 5];
549 let n = file.read(0, &mut buf).unwrap();
550 assert_eq!(n, 5);
551 assert_eq!(&buf, b"Hello");
552 }
553
554 #[test]
555 fn test_read_from_directory_fails() {
556 let fs = RamFs::new();
557 let root = fs.root();
558
559 let mut buf = vec![0u8; 10];
560 let result = root.read(0, &mut buf);
561 assert!(result.is_err());
562 assert_eq!(result.unwrap_err(), KernelError::FsError(FsError::NotAFile));
563 }
564
565 #[test]
566 fn test_write_to_directory_fails() {
567 let fs = RamFs::new();
568 let root = fs.root();
569
570 let result = root.write(0, b"data");
571 assert!(result.is_err());
572 assert_eq!(result.unwrap_err(), KernelError::FsError(FsError::NotAFile));
573 }
574
575 #[test]
578 fn test_file_metadata() {
579 let fs = RamFs::new();
580 let root = fs.root();
581 let file = root.create("meta.txt", Permissions::default()).unwrap();
582 file.write(0, b"content").unwrap();
583
584 let meta = file.metadata().unwrap();
585 assert_eq!(meta.node_type, NodeType::File);
586 assert_eq!(meta.size, 7);
587 }
588
589 #[test]
590 fn test_directory_metadata() {
591 let fs = RamFs::new();
592 let root = fs.root();
593 let meta = root.metadata().unwrap();
594 assert_eq!(meta.node_type, NodeType::Directory);
595 }
596
597 #[test]
600 fn test_truncate_file() {
601 let fs = RamFs::new();
602 let root = fs.root();
603 let file = root.create("trunc.txt", Permissions::default()).unwrap();
604 file.write(0, b"Hello, World!").unwrap();
605
606 file.truncate(5).unwrap();
608
609 let meta = file.metadata().unwrap();
610 assert_eq!(meta.size, 5);
611
612 let mut buf = vec![0u8; 10];
613 let n = file.read(0, &mut buf).unwrap();
614 assert_eq!(n, 5);
615 assert_eq!(&buf[..5], b"Hello");
616 }
617
618 #[test]
619 fn test_truncate_to_zero() {
620 let fs = RamFs::new();
621 let root = fs.root();
622 let file = root.create("empty.txt", Permissions::default()).unwrap();
623 file.write(0, b"data").unwrap();
624
625 file.truncate(0).unwrap();
626 let meta = file.metadata().unwrap();
627 assert_eq!(meta.size, 0);
628 }
629
630 #[test]
631 fn test_truncate_directory_fails() {
632 let fs = RamFs::new();
633 let root = fs.root();
634 let result = root.truncate(0);
635 assert!(result.is_err());
636 assert_eq!(result.unwrap_err(), KernelError::FsError(FsError::NotAFile));
637 }
638
639 #[test]
642 fn test_mkdir() {
643 let fs = RamFs::new();
644 let root = fs.root();
645
646 let dir = root.mkdir("subdir", Permissions::default());
647 assert!(dir.is_ok());
648 assert_eq!(dir.unwrap().node_type(), NodeType::Directory);
649 }
650
651 #[test]
652 fn test_mkdir_duplicate_fails() {
653 let fs = RamFs::new();
654 let root = fs.root();
655
656 root.mkdir("dup", Permissions::default()).unwrap();
657 let result = root.mkdir("dup", Permissions::default());
658 assert!(result.is_err());
659 assert_eq!(
660 result.err().expect("expected Err"),
661 KernelError::FsError(FsError::AlreadyExists)
662 );
663 }
664
665 #[test]
666 fn test_mkdir_on_file_fails() {
667 let fs = RamFs::new();
668 let root = fs.root();
669 let file = root.create("file", Permissions::default()).unwrap();
670
671 let result = file.mkdir("subdir", Permissions::default());
672 assert!(result.is_err());
673 assert_eq!(
674 result.err().expect("expected Err"),
675 KernelError::FsError(FsError::NotADirectory)
676 );
677 }
678
679 #[test]
680 fn test_lookup() {
681 let fs = RamFs::new();
682 let root = fs.root();
683
684 root.create("myfile", Permissions::default()).unwrap();
685
686 let found = root.lookup("myfile");
687 assert!(found.is_ok());
688 assert_eq!(found.unwrap().node_type(), NodeType::File);
689 }
690
691 #[test]
692 fn test_lookup_not_found() {
693 let fs = RamFs::new();
694 let root = fs.root();
695
696 let result = root.lookup("missing");
697 assert!(result.is_err());
698 assert_eq!(
699 result.err().expect("expected Err"),
700 KernelError::FsError(FsError::NotFound)
701 );
702 }
703
704 #[test]
705 fn test_lookup_on_file_fails() {
706 let fs = RamFs::new();
707 let root = fs.root();
708 let file = root.create("f", Permissions::default()).unwrap();
709
710 let result = file.lookup("anything");
711 assert!(result.is_err());
712 assert_eq!(
713 result.err().expect("expected Err"),
714 KernelError::FsError(FsError::NotADirectory)
715 );
716 }
717
718 #[test]
719 fn test_readdir() {
720 let fs = RamFs::new();
721 let root = fs.root();
722
723 root.create("file1", Permissions::default()).unwrap();
724 root.mkdir("dir1", Permissions::default()).unwrap();
725
726 let entries = root.readdir().unwrap();
727 assert_eq!(entries.len(), 4);
729
730 let names: Vec<&str> = entries.iter().map(|e| e.name.as_str()).collect();
731 assert!(names.contains(&"."));
732 assert!(names.contains(&".."));
733 assert!(names.contains(&"file1"));
734 assert!(names.contains(&"dir1"));
735 }
736
737 #[test]
738 fn test_readdir_on_file_fails() {
739 let fs = RamFs::new();
740 let root = fs.root();
741 let file = root.create("f", Permissions::default()).unwrap();
742
743 let result = file.readdir();
744 assert!(result.is_err());
745 assert_eq!(
746 result.err().expect("expected Err"),
747 KernelError::FsError(FsError::NotADirectory)
748 );
749 }
750
751 #[test]
754 fn test_unlink_file() {
755 let fs = RamFs::new();
756 let root = fs.root();
757
758 root.create("victim", Permissions::default()).unwrap();
759 let result = root.unlink("victim");
760 assert!(result.is_ok());
761
762 assert!(root.lookup("victim").is_err());
764 }
765
766 #[test]
767 fn test_unlink_empty_directory() {
768 let fs = RamFs::new();
769 let root = fs.root();
770
771 root.mkdir("emptydir", Permissions::default()).unwrap();
772 let result = root.unlink("emptydir");
773 assert!(result.is_ok());
774 }
775
776 #[test]
777 fn test_unlink_nonempty_directory_fails() {
778 let fs = RamFs::new();
779 let root = fs.root();
780
781 let dir = root.mkdir("notempty", Permissions::default()).unwrap();
782 dir.create("child", Permissions::default()).unwrap();
783
784 let result = root.unlink("notempty");
785 assert!(result.is_err());
786 assert_eq!(
787 result.err().expect("expected Err"),
788 KernelError::FsError(FsError::DirectoryNotEmpty)
789 );
790 }
791
792 #[test]
793 fn test_unlink_not_found() {
794 let fs = RamFs::new();
795 let root = fs.root();
796
797 let result = root.unlink("phantom");
798 assert!(result.is_err());
799 assert_eq!(result.unwrap_err(), KernelError::FsError(FsError::NotFound));
800 }
801
802 #[test]
803 fn test_unlink_on_file_fails() {
804 let fs = RamFs::new();
805 let root = fs.root();
806 let file = root.create("f", Permissions::default()).unwrap();
807
808 let result = file.unlink("anything");
809 assert!(result.is_err());
810 assert_eq!(
811 result.err().expect("expected Err"),
812 KernelError::FsError(FsError::NotADirectory)
813 );
814 }
815
816 #[test]
817 fn test_create_on_file_fails() {
818 let fs = RamFs::new();
819 let root = fs.root();
820 let file = root.create("f", Permissions::default()).unwrap();
821
822 let result = file.create("sub", Permissions::default());
823 assert!(result.is_err());
824 assert_eq!(
825 result.err().expect("expected Err"),
826 KernelError::FsError(FsError::NotADirectory)
827 );
828 }
829}