1use alloc::{
28 boxed::Box,
29 collections::BTreeMap,
30 format,
31 string::{String, ToString},
32 sync::{Arc, Weak},
33 vec::Vec,
34};
35use core::any::Any;
36use spin::RwLock;
37
38use crate::device::{Device, DeviceType, manager::DeviceManager};
39use crate::object::capability::{ControlOps, StreamError, StreamOps};
40use crate::{
41 driver_initcall,
42 fs::{
43 DeviceFileInfo, FileMetadata, FileObject, FilePermission, FileSystemDriver,
44 FileSystemError, FileSystemErrorKind, FileSystemType, FileType, SeekFrom,
45 get_fs_driver_manager,
46 },
47 object::capability::MemoryMappingOps,
48};
49
50use super::super::core::{DirectoryEntryInternal, FileSystemId, FileSystemOperations, VfsNode};
51
52pub struct DevFS {
58 fs_id: FileSystemId,
60 root: RwLock<Arc<DevNode>>,
62 name: String,
64}
65
66impl DevFS {
67 pub fn new() -> Arc<Self> {
69 let root = Arc::new(DevNode::new_directory("/".to_string()));
70 let fs = Arc::new(Self {
71 fs_id: FileSystemId::new(),
72 root: RwLock::new(Arc::clone(&root)),
73 name: "devfs".to_string(),
74 });
75 let fs_weak = Arc::downgrade(&(fs.clone() as Arc<dyn FileSystemOperations>));
76 root.set_filesystem(fs_weak);
77 fs
78 }
79
80 fn populate_devices(&self) -> Result<(), FileSystemError> {
82 let device_manager = DeviceManager::get_manager();
83 let root = self.root.read();
84
85 root.clear_children();
87
88 let named_devices = device_manager.get_named_devices();
90
91 for (device_name, device) in named_devices {
92 let device_type = device.device_type();
93
94 match device_type {
96 DeviceType::Char | DeviceType::Block => {
97 let device_id = device_manager
99 .get_device_id_by_name(&device_name)
100 .unwrap_or(0); let device_file_info = DeviceFileInfo {
103 device_id,
104 device_type,
105 };
106
107 let file_type = match device_type {
108 DeviceType::Char => FileType::CharDevice(device_file_info),
109 DeviceType::Block => FileType::BlockDevice(device_file_info),
110 _ => continue, };
112
113 let device_node = Arc::new(DevNode::new_device_file(
114 device_name.clone(),
115 file_type,
116 device_id as u64, ));
118
119 if let Some(fs_ref) = root.filesystem() {
121 device_node.set_filesystem(fs_ref);
122 }
123
124 root.add_child(device_name, device_node)?;
125 }
126 _ => {} }
128 }
129
130 Ok(())
131 }
132}
133
134impl FileSystemOperations for DevFS {
135 fn fs_id(&self) -> FileSystemId {
136 self.fs_id
137 }
138
139 fn name(&self) -> &str {
140 &self.name
141 }
142
143 fn root_node(&self) -> Arc<dyn VfsNode> {
144 let _ = self.populate_devices();
146 Arc::clone(&*self.root.read()) as Arc<dyn VfsNode>
147 }
148
149 fn lookup(
150 &self,
151 parent: &Arc<dyn VfsNode>,
152 name: &String,
153 ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
154 let _ = self.populate_devices();
156
157 let dev_node = Arc::downcast::<DevNode>(parent.clone()).map_err(|_| {
158 FileSystemError::new(
159 FileSystemErrorKind::NotSupported,
160 "Invalid node type for DevFS",
161 )
162 })?;
163
164 if let Some(child) = dev_node.get_child(name) {
165 Ok(child as Arc<dyn VfsNode>)
166 } else {
167 Err(FileSystemError::new(
168 FileSystemErrorKind::NotFound,
169 format!("Device '{}' not found in devfs", name),
170 ))
171 }
172 }
173
174 fn readdir(
175 &self,
176 node: &Arc<dyn VfsNode>,
177 ) -> Result<Vec<DirectoryEntryInternal>, FileSystemError> {
178 let _ = self.populate_devices();
180
181 let dev_node = Arc::downcast::<DevNode>(node.clone()).map_err(|_| {
182 FileSystemError::new(
183 FileSystemErrorKind::NotSupported,
184 "Invalid node type for DevFS",
185 )
186 })?;
187
188 dev_node.readdir()
189 }
190
191 fn open(
192 &self,
193 node: &Arc<dyn VfsNode>,
194 _flags: u32,
195 ) -> Result<Arc<dyn FileObject>, FileSystemError> {
196 let dev_node = Arc::downcast::<DevNode>(node.clone()).map_err(|_| {
197 FileSystemError::new(
198 FileSystemErrorKind::NotSupported,
199 "Invalid node type for DevFS",
200 )
201 })?;
202
203 dev_node.open()
204 }
205
206 fn is_read_only(&self) -> bool {
207 true
208 }
209
210 fn create(
212 &self,
213 _parent: &Arc<dyn VfsNode>,
214 _name: &String,
215 _file_type: FileType,
216 _mode: u32,
217 ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
218 Err(FileSystemError::new(
219 FileSystemErrorKind::ReadOnly,
220 "DevFS is read-only: cannot create files",
221 ))
222 }
223
224 fn remove(&self, _parent: &Arc<dyn VfsNode>, _name: &String) -> Result<(), FileSystemError> {
225 Err(FileSystemError::new(
226 FileSystemErrorKind::ReadOnly,
227 "DevFS is read-only: cannot remove files",
228 ))
229 }
230
231 fn as_any(&self) -> &dyn Any {
232 self
233 }
234}
235
236pub struct DevNode {
238 name: String,
240 file_type: FileType,
242 file_id: u64,
244 children: RwLock<BTreeMap<String, Arc<DevNode>>>,
246 filesystem: RwLock<Option<Weak<dyn FileSystemOperations>>>,
248}
249
250impl Clone for DevNode {
251 fn clone(&self) -> Self {
252 Self {
253 name: self.name.clone(),
254 file_type: self.file_type.clone(),
255 file_id: self.file_id,
256 children: RwLock::new(self.children.read().clone()),
257 filesystem: RwLock::new(self.filesystem.read().clone()),
258 }
259 }
260}
261
262impl DevNode {
263 pub fn new_directory(name: String) -> Self {
265 Self {
266 name,
267 file_type: FileType::Directory,
268 file_id: 0, children: RwLock::new(BTreeMap::new()),
270 filesystem: RwLock::new(None),
271 }
272 }
273
274 pub fn new_device_file(name: String, file_type: FileType, file_id: u64) -> Self {
276 Self {
277 name,
278 file_type,
279 file_id,
280 children: RwLock::new(BTreeMap::new()),
281 filesystem: RwLock::new(None),
282 }
283 }
284
285 pub fn set_filesystem(&self, fs: Weak<dyn FileSystemOperations>) {
287 *self.filesystem.write() = Some(fs);
288 }
289
290 pub fn add_child(&self, name: String, child: Arc<DevNode>) -> Result<(), FileSystemError> {
292 if self.file_type != FileType::Directory {
293 return Err(FileSystemError::new(
294 FileSystemErrorKind::NotADirectory,
295 "Cannot add child to non-directory node",
296 ));
297 }
298
299 let mut children = self.children.write();
300 children.insert(name, child);
301 Ok(())
302 }
303
304 pub fn get_child(&self, name: &str) -> Option<Arc<DevNode>> {
306 let children = self.children.read();
307 children.get(name).cloned()
308 }
309
310 pub fn clear_children(&self) {
312 let mut children = self.children.write();
313 children.clear();
314 }
315
316 pub fn readdir(&self) -> Result<Vec<DirectoryEntryInternal>, FileSystemError> {
318 if self.file_type != FileType::Directory {
319 return Err(FileSystemError::new(
320 FileSystemErrorKind::NotADirectory,
321 "Cannot read directory of non-directory node",
322 ));
323 }
324
325 let children = self.children.read();
326 let mut entries = Vec::new();
327
328 entries.push(DirectoryEntryInternal {
330 name: ".".to_string(),
331 file_type: FileType::Directory,
332 file_id: self.file_id,
333 });
334
335 entries.push(DirectoryEntryInternal {
338 name: "..".to_string(),
339 file_type: FileType::Directory,
340 file_id: self.file_id, });
342
343 for (name, child) in children.iter() {
345 entries.push(DirectoryEntryInternal {
346 name: name.clone(),
347 file_type: child.file_type.clone(),
348 file_id: child.file_id,
349 });
350 }
351
352 Ok(entries)
353 }
354
355 pub fn open(&self) -> Result<Arc<dyn FileObject>, FileSystemError> {
357 match self.file_type {
358 FileType::CharDevice(device_info) | FileType::BlockDevice(device_info) => {
359 Ok(Arc::new(DevFileObject::new(
361 Arc::new(self.clone()),
362 device_info.device_id,
363 device_info.device_type,
364 )?))
365 }
366 FileType::Directory => {
367 Ok(Arc::new(DevDirectoryObject::new(Arc::new(self.clone()))))
369 }
370 _ => Err(FileSystemError::new(
371 FileSystemErrorKind::NotSupported,
372 "Unsupported file type in devfs",
373 )),
374 }
375 }
376}
377
378impl VfsNode for DevNode {
379 fn id(&self) -> u64 {
380 self.file_id
381 }
382
383 fn metadata(&self) -> Result<FileMetadata, FileSystemError> {
384 Ok(FileMetadata {
385 file_type: self.file_type.clone(),
386 size: 0, permissions: FilePermission {
388 read: true,
389 write: true,
390 execute: false,
391 },
392 created_time: 0,
393 modified_time: 0,
394 accessed_time: 0,
395 file_id: self.file_id,
396 link_count: 1,
397 })
398 }
399
400 fn filesystem(&self) -> Option<Weak<dyn FileSystemOperations>> {
401 self.filesystem.read().clone()
402 }
403
404 fn as_any(&self) -> &dyn Any {
405 self
406 }
407}
408
409pub struct DevFSDriver;
411
412pub struct DevFileObject {
417 node: Arc<DevNode>,
419 position: RwLock<u64>,
421 #[allow(dead_code)]
423 device_id: usize,
424 #[allow(dead_code)]
426 device_type: DeviceType,
427 device_guard: Option<Arc<dyn Device>>,
429}
430
431impl DevFileObject {
432 pub fn new(
434 node: Arc<DevNode>,
435 device_id: usize,
436 device_type: DeviceType,
437 ) -> Result<Self, FileSystemError> {
438 match DeviceManager::get_manager().get_device(device_id) {
440 Some(device_guard) => Ok(Self {
441 node,
442 position: RwLock::new(0),
443 device_id,
444 device_type,
445 device_guard: Some(device_guard),
446 }),
447 None => Err(FileSystemError::new(
448 FileSystemErrorKind::DeviceError,
449 format!("Device with ID {} not found in DeviceManager", device_id),
450 )),
451 }
452 }
453
454 fn read_device(&self, buffer: &mut [u8]) -> Result<usize, FileSystemError> {
456 if let Some(ref device_guard) = self.device_guard {
457 let device_guard_ref = device_guard.as_ref();
458 let position = *self.position.read();
459
460 match device_guard_ref.device_type() {
461 DeviceType::Char => {
462 if let Some(char_device) = device_guard_ref.as_char_device() {
463 match char_device.read_at(position, buffer) {
465 Ok(bytes_read) => {
466 *self.position.write() += bytes_read as u64;
468 Ok(bytes_read)
469 }
470 Err(e) => Err(FileSystemError::new(
471 FileSystemErrorKind::IoError,
472 format!("Character device read failed: {}", e),
473 )),
474 }
475 } else {
476 return Err(FileSystemError::new(
477 FileSystemErrorKind::DeviceError,
478 "Device does not support character operations",
479 ));
480 }
481 }
482 DeviceType::Block => {
483 if let Some(block_device) = device_guard_ref.as_block_device() {
484 let request = Box::new(crate::device::block::request::BlockIORequest {
486 request_type: crate::device::block::request::BlockIORequestType::Read,
487 sector: 0,
488 sector_count: 1,
489 head: 0,
490 cylinder: 0,
491 buffer: buffer.to_vec(),
492 });
493
494 block_device.enqueue_request(request);
495 let results = block_device.process_requests();
496
497 if let Some(result) = results.first() {
498 match &result.result {
499 Ok(_) => {
500 let bytes_to_copy =
502 core::cmp::min(buffer.len(), result.request.buffer.len());
503 buffer[..bytes_to_copy]
504 .copy_from_slice(&result.request.buffer[..bytes_to_copy]);
505 return Ok(bytes_to_copy);
506 }
507 Err(e) => {
508 return Err(FileSystemError::new(
509 FileSystemErrorKind::IoError,
510 format!("Block device read failed: {}", e),
511 ));
512 }
513 }
514 }
515 return Ok(0);
516 } else {
517 return Err(FileSystemError::new(
518 FileSystemErrorKind::DeviceError,
519 "Device does not support block operations",
520 ));
521 }
522 }
523 _ => {
524 return Err(FileSystemError::new(
525 FileSystemErrorKind::DeviceError,
526 "Unsupported device type",
527 ));
528 }
529 }
530 } else {
531 Err(FileSystemError::new(
532 FileSystemErrorKind::DeviceError,
533 "No device guard available",
534 ))
535 }
536 }
537
538 fn write_device(&self, buffer: &[u8]) -> Result<usize, FileSystemError> {
540 if let Some(ref device_guard) = self.device_guard {
541 let device_guard_ref = device_guard.as_ref();
542 let position = *self.position.read();
543
544 match device_guard_ref.device_type() {
545 DeviceType::Char => {
546 if let Some(char_device) = device_guard_ref.as_char_device() {
547 match char_device.write_at(position, buffer) {
549 Ok(bytes_written) => {
550 *self.position.write() += bytes_written as u64;
552 Ok(bytes_written)
553 }
554 Err(e) => Err(FileSystemError::new(
555 FileSystemErrorKind::IoError,
556 format!("Character device write failed: {}", e),
557 )),
558 }
559 } else {
560 return Err(FileSystemError::new(
561 FileSystemErrorKind::DeviceError,
562 "Device does not support character operations",
563 ));
564 }
565 }
566 DeviceType::Block => {
567 if let Some(block_device) = device_guard_ref.as_block_device() {
568 let request = Box::new(crate::device::block::request::BlockIORequest {
569 request_type: crate::device::block::request::BlockIORequestType::Write,
570 sector: 0,
571 sector_count: 1,
572 head: 0,
573 cylinder: 0,
574 buffer: buffer.to_vec(),
575 });
576
577 block_device.enqueue_request(request);
578 let results = block_device.process_requests();
579
580 if let Some(result) = results.first() {
581 match &result.result {
582 Ok(_) => return Ok(buffer.len()),
583 Err(e) => {
584 return Err(FileSystemError::new(
585 FileSystemErrorKind::IoError,
586 format!("Block device write failed: {}", e),
587 ));
588 }
589 }
590 }
591 return Ok(0);
592 } else {
593 return Err(FileSystemError::new(
594 FileSystemErrorKind::DeviceError,
595 "Device does not support block operations",
596 ));
597 }
598 }
599 _ => {
600 return Err(FileSystemError::new(
601 FileSystemErrorKind::DeviceError,
602 "Unsupported device type",
603 ));
604 }
605 }
606 } else {
607 Err(FileSystemError::new(
608 FileSystemErrorKind::DeviceError,
609 "No device guard available",
610 ))
611 }
612 }
613}
614
615impl StreamOps for DevFileObject {
616 fn read(&self, buffer: &mut [u8]) -> Result<usize, StreamError> {
617 self.read_device(buffer).map_err(StreamError::from)
618 }
619
620 fn write(&self, buffer: &[u8]) -> Result<usize, StreamError> {
621 self.write_device(buffer).map_err(StreamError::from)
622 }
623}
624
625impl ControlOps for DevFileObject {
626 fn control(&self, command: u32, arg: usize) -> Result<i32, &'static str> {
627 if let Some(ref device_guard) = self.device_guard {
629 let device_guard_ref = device_guard.as_ref();
630 device_guard_ref.control(command, arg)
632 } else {
633 Err("No device available for control operations")
634 }
635 }
636
637 fn supported_control_commands(&self) -> alloc::vec::Vec<(u32, &'static str)> {
638 if let Some(ref device_guard) = self.device_guard {
640 let device_guard_ref = device_guard.as_ref();
641 device_guard_ref.supported_control_commands()
642 } else {
643 alloc::vec![]
644 }
645 }
646}
647
648impl MemoryMappingOps for DevFileObject {
649 fn get_mapping_info(
650 &self,
651 offset: usize,
652 length: usize,
653 ) -> Result<(usize, usize, bool), &'static str> {
654 if let Some(ref device_guard) = self.device_guard {
656 let device_guard_ref = device_guard.as_ref();
657 device_guard_ref.get_mapping_info(offset, length)
658 } else {
659 Err("No device associated with this DevFileObject")
660 }
661 }
662
663 fn on_mapped(&self, vaddr: usize, paddr: usize, length: usize, offset: usize) {
664 if let Some(ref device_guard) = self.device_guard {
665 let device_guard_ref = device_guard.as_ref();
666 device_guard_ref.on_mapped(vaddr, paddr, length, offset);
667 }
668 }
669
670 fn on_unmapped(&self, vaddr: usize, length: usize) {
671 if let Some(ref device_guard) = self.device_guard {
672 let device_guard_ref = device_guard.as_ref();
673 device_guard_ref.on_unmapped(vaddr, length);
674 }
675 }
676
677 fn supports_mmap(&self) -> bool {
678 if let Some(ref device_guard) = self.device_guard {
679 let device_guard_ref = device_guard.as_ref();
680 device_guard_ref.supports_mmap()
681 } else {
682 false
683 }
684 }
685}
686
687impl FileObject for DevFileObject {
688 fn seek(&self, whence: SeekFrom) -> Result<u64, StreamError> {
689 let mut position = self.position.write();
690
691 let new_pos = match whence {
692 SeekFrom::Start(offset) => offset,
693 SeekFrom::Current(offset) => {
694 if offset >= 0 {
695 *position + offset as u64
696 } else {
697 position.saturating_sub((-offset) as u64)
698 }
699 }
700 SeekFrom::End(offset) => {
701 return Err(StreamError::from(FileSystemError::new(
705 FileSystemErrorKind::NotSupported,
706 "Seek from end not supported for device files",
707 )));
708 }
709 };
710
711 *position = new_pos;
712 Ok(new_pos)
713 }
714
715 fn metadata(&self) -> Result<FileMetadata, StreamError> {
716 self.node.metadata().map_err(StreamError::from)
717 }
718
719 fn truncate(&self, _size: u64) -> Result<(), StreamError> {
720 Err(StreamError::from(FileSystemError::new(
722 FileSystemErrorKind::NotSupported,
723 "Cannot truncate device files",
724 )))
725 }
726
727 fn as_any(&self) -> &dyn Any {
728 self
729 }
730}
731
732impl crate::object::capability::selectable::Selectable for DevFileObject {
733 fn current_ready(
734 &self,
735 interest: crate::object::capability::selectable::ReadyInterest,
736 ) -> crate::object::capability::selectable::ReadySet {
737 if let Some(ref device_guard) = self.device_guard {
739 return device_guard.as_ref().current_ready(interest);
740 }
741 crate::object::capability::selectable::Selectable::current_ready(self, interest)
742 }
743
744 fn wait_until_ready(
745 &self,
746 interest: crate::object::capability::selectable::ReadyInterest,
747 trapframe: &mut crate::arch::Trapframe,
748 timeout_ticks: Option<u64>,
749 ) -> crate::object::capability::selectable::SelectWaitOutcome {
750 if let Some(ref device_guard) = self.device_guard {
751 return device_guard
752 .as_ref()
753 .wait_until_ready(interest, trapframe, timeout_ticks);
754 }
755 let _ = (interest, trapframe, timeout_ticks);
756 crate::object::capability::selectable::SelectWaitOutcome::Ready
757 }
758
759 fn set_nonblocking(&self, enabled: bool) {
760 if let Some(ref device_guard) = self.device_guard {
761 device_guard.as_ref().set_nonblocking(enabled);
762 }
763 }
764
765 fn is_nonblocking(&self) -> bool {
766 if let Some(ref device_guard) = self.device_guard {
767 return device_guard.as_ref().is_nonblocking();
768 }
769 crate::object::capability::selectable::Selectable::is_nonblocking(self)
770 }
771}
772
773pub struct DevDirectoryObject {
778 node: Arc<DevNode>,
780 position: RwLock<usize>,
782}
783
784impl DevDirectoryObject {
785 pub fn new(node: Arc<DevNode>) -> Self {
787 Self {
788 node,
789 position: RwLock::new(0),
790 }
791 }
792}
793
794impl StreamOps for DevDirectoryObject {
795 fn read(&self, buffer: &mut [u8]) -> Result<usize, StreamError> {
796 let entries = self.node.readdir().map_err(StreamError::from)?;
798 let position = *self.position.read();
799
800 if position >= entries.len() {
801 return Ok(0); }
803
804 let internal_entry = &entries[position];
806
807 let internal_with_size = crate::fs::DirectoryEntryInternal {
809 name: internal_entry.name.clone(),
810 file_type: internal_entry.file_type.clone(),
811 size: 0, file_id: internal_entry.file_id,
813 metadata: None,
814 };
815
816 let dir_entry = crate::fs::DirectoryEntry::from_internal(&internal_with_size);
817 let entry_size = dir_entry.entry_size();
818
819 if buffer.len() < entry_size {
820 return Err(StreamError::InvalidArgument); }
822
823 let entry_bytes =
825 unsafe { core::slice::from_raw_parts(&dir_entry as *const _ as *const u8, entry_size) };
826
827 buffer[..entry_size].copy_from_slice(entry_bytes);
828
829 *self.position.write() += 1;
831
832 Ok(entry_size)
833 }
834
835 fn write(&self, _buffer: &[u8]) -> Result<usize, StreamError> {
836 Err(StreamError::from(FileSystemError::new(
837 FileSystemErrorKind::ReadOnly,
838 "Cannot write to directory in devfs",
839 )))
840 }
841}
842
843impl ControlOps for DevDirectoryObject {
844 fn control(&self, _command: u32, _arg: usize) -> Result<i32, &'static str> {
846 Err("Control operations not supported on directories")
847 }
848}
849
850impl MemoryMappingOps for DevDirectoryObject {
851 fn get_mapping_info(
852 &self,
853 _offset: usize,
854 _length: usize,
855 ) -> Result<(usize, usize, bool), &'static str> {
856 Err("Memory mapping not supported for directories")
857 }
858
859 fn on_mapped(&self, _vaddr: usize, _paddr: usize, _length: usize, _offset: usize) {
860 }
862
863 fn on_unmapped(&self, _vaddr: usize, _length: usize) {
864 }
866
867 fn supports_mmap(&self) -> bool {
868 false
869 }
870}
871
872impl FileObject for DevDirectoryObject {
873 fn seek(&self, whence: SeekFrom) -> Result<u64, StreamError> {
874 let entries = self.node.readdir().map_err(StreamError::from)?;
876 let entry_count = entries.len() as u64;
877
878 let mut position = self.position.write();
879
880 let new_pos = match whence {
881 SeekFrom::Start(offset) => offset,
882 SeekFrom::Current(offset) => {
883 if offset >= 0 {
884 *position as u64 + offset as u64
885 } else {
886 (*position as u64).saturating_sub((-offset) as u64)
887 }
888 }
889 SeekFrom::End(offset) => {
890 if offset >= 0 {
891 entry_count + offset as u64
892 } else {
893 entry_count.saturating_sub((-offset) as u64)
894 }
895 }
896 };
897
898 *position = new_pos as usize;
899 Ok(new_pos)
900 }
901
902 fn metadata(&self) -> Result<FileMetadata, StreamError> {
903 self.node.metadata().map_err(StreamError::from)
904 }
905
906 fn truncate(&self, _size: u64) -> Result<(), StreamError> {
907 Err(StreamError::from(FileSystemError::new(
908 FileSystemErrorKind::ReadOnly,
909 "Cannot truncate directory in devfs",
910 )))
911 }
912
913 fn as_any(&self) -> &dyn Any {
914 self
915 }
916}
917
918impl crate::object::capability::selectable::Selectable for DevDirectoryObject {
919 fn current_ready(
920 &self,
921 interest: crate::object::capability::selectable::ReadyInterest,
922 ) -> crate::object::capability::selectable::ReadySet {
923 let mut set = crate::object::capability::selectable::ReadySet::none();
924 if interest.read {
925 set.read = true;
926 }
927 if interest.write {
928 set.write = true;
929 }
930 if interest.except {
931 set.except = false;
932 }
933 set
934 }
935
936 fn wait_until_ready(
937 &self,
938 _interest: crate::object::capability::selectable::ReadyInterest,
939 _trapframe: &mut crate::arch::Trapframe,
940 _timeout_ticks: Option<u64>,
941 ) -> crate::object::capability::selectable::SelectWaitOutcome {
942 crate::object::capability::selectable::SelectWaitOutcome::Ready
943 }
944
945 fn is_nonblocking(&self) -> bool {
946 true
947 }
948}
949
950impl FileSystemDriver for DevFSDriver {
951 fn name(&self) -> &'static str {
952 "devfs"
953 }
954
955 fn filesystem_type(&self) -> FileSystemType {
956 FileSystemType::Device
957 }
958
959 fn create(&self) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
960 Ok(DevFS::new() as Arc<dyn FileSystemOperations>)
961 }
962
963 fn create_from_option_string(
964 &self,
965 _options: &str,
966 ) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
967 self.create()
969 }
970}
971
972fn register_driver() {
974 let fs_driver_manager = get_fs_driver_manager();
975 fs_driver_manager.register_driver(Box::new(DevFSDriver));
976}
977
978driver_initcall!(register_driver);
979
980#[cfg(test)]
981mod tests {
982 use super::*;
983 use crate::device::{GenericDevice, manager::DeviceManager};
984 use alloc::sync::Arc;
985
986 #[test_case]
987 fn test_devfs_creation() {
988 let devfs = DevFS::new();
989 assert_eq!(devfs.name(), "devfs");
990 }
991
992 #[test_case]
993 fn test_devfs_root_access() {
994 let devfs = DevFS::new();
995 let root = devfs.root_node();
996 assert_eq!(root.id(), 0);
997
998 let metadata = root.metadata().unwrap();
999 assert_eq!(metadata.file_type, FileType::Directory);
1000 }
1001
1002 #[test_case]
1003 fn test_devfs_device_discovery() {
1004 let device_manager = DeviceManager::get_manager();
1006 let test_device = Arc::new(GenericDevice::new("test_devfs_device"));
1007 let _device_id =
1008 device_manager.register_device_with_name("test_devfs_device".to_string(), test_device);
1009
1010 let devfs = DevFS::new();
1011 let root = devfs.root_node();
1012
1013 let entries = devfs.readdir(&root).unwrap();
1015
1016 assert!(
1019 entries.len() == 0 || entries.len() > 0,
1020 "DevFS readdir should work without error"
1021 );
1022 }
1023
1024 #[test_case]
1025 fn test_devfs_lookup() {
1026 let devfs = DevFS::new();
1027 let root = devfs.root_node();
1028
1029 let result = devfs.lookup(&root, &"nonexistent_device".to_string());
1031 assert!(result.is_err(), "Lookup of non-existent device should fail");
1032
1033 let error = result.unwrap_err();
1034 assert_eq!(error.kind, FileSystemErrorKind::NotFound);
1035 }
1036
1037 #[test_case]
1038 fn test_devfs_with_real_devices() {
1039 use crate::device::block::mockblk::MockBlockDevice;
1040 use crate::device::char::mockchar::MockCharDevice;
1041
1042 let device_manager = DeviceManager::get_manager();
1044
1045 let char_device = Arc::new(MockCharDevice::new("tty0"));
1047 let _char_device_id =
1048 device_manager.register_device_with_name("tty0".to_string(), char_device.clone());
1049
1050 let block_device = Arc::new(MockBlockDevice::new("sda", 512, 1000));
1052 let _block_device_id =
1053 device_manager.register_device_with_name("sda".to_string(), block_device.clone());
1054
1055 let devfs = DevFS::new();
1057 let root = devfs.root_node();
1058
1059 let entries = devfs.readdir(&root).unwrap();
1061
1062 let _unused_entries = &entries;
1064
1065 let has_tty0 = entries.iter().any(|entry| {
1067 entry.name == "tty0" && matches!(entry.file_type, FileType::CharDevice(_))
1068 });
1069 let has_sda = entries.iter().any(|entry| {
1070 entry.name == "sda" && matches!(entry.file_type, FileType::BlockDevice(_))
1071 });
1072
1073 assert!(has_tty0, "DevFS should contain tty0 character device");
1074 assert!(has_sda, "DevFS should contain sda block device");
1075
1076 let tty0_result = devfs.lookup(&root, &"tty0".to_string());
1078 assert!(tty0_result.is_ok(), "Should be able to lookup tty0");
1079
1080 let sda_result = devfs.lookup(&root, &"sda".to_string());
1082 assert!(sda_result.is_ok(), "Should be able to lookup sda");
1083 }
1084
1085 #[test_case]
1086 fn test_devfs_driver_registration() {
1087 let fs_driver_manager = get_fs_driver_manager();
1089
1090 assert!(
1092 fs_driver_manager.has_driver("devfs"),
1093 "DevFS driver should be registered"
1094 );
1095
1096 let driver_type = fs_driver_manager.get_driver_type("devfs");
1098 assert_eq!(driver_type, Some(FileSystemType::Device));
1099
1100 let devfs_result = fs_driver_manager.create_from_option_string("devfs", "");
1102 assert!(
1103 devfs_result.is_ok(),
1104 "Should be able to create DevFS through driver manager"
1105 );
1106
1107 let devfs_instance = devfs_result.unwrap();
1108 assert_eq!(devfs_instance.name(), "devfs");
1109 assert!(devfs_instance.is_read_only());
1110 }
1111
1112 #[test_case]
1113 fn test_devfs_readonly_operations() {
1114 let devfs = DevFS::new();
1115 let root = devfs.root_node();
1116
1117 let create_result = devfs.create(&root, &"test_file".to_string(), FileType::RegularFile, 0);
1119 assert!(create_result.is_err());
1120 assert_eq!(
1121 create_result.unwrap_err().kind,
1122 FileSystemErrorKind::ReadOnly
1123 );
1124
1125 let remove_result = devfs.remove(&root, &"test_file".to_string());
1127 assert!(remove_result.is_err());
1128 assert_eq!(
1129 remove_result.unwrap_err().kind,
1130 FileSystemErrorKind::ReadOnly
1131 );
1132 }
1133
1134 #[test_case]
1135 fn test_devfs_device_file_operations() {
1136 use crate::device::char::mockchar::MockCharDevice;
1137
1138 let device_manager = DeviceManager::get_manager();
1140 let char_device = Arc::new(MockCharDevice::new("test_char_dev"));
1141 let _device_id = device_manager
1142 .register_device_with_name("test_char_dev".to_string(), char_device.clone());
1143
1144 let devfs = DevFS::new();
1146 let root = devfs.root_node();
1147
1148 let device_node_result = devfs.lookup(&root, &"test_char_dev".to_string());
1149 assert!(
1150 device_node_result.is_ok(),
1151 "Should be able to lookup character device"
1152 );
1153
1154 let device_node = device_node_result.unwrap();
1155
1156 let file_result = devfs.open(&device_node, 0);
1158 assert!(
1159 file_result.is_ok(),
1160 "Should be able to open character device file"
1161 );
1162
1163 let file_obj = file_result.unwrap();
1164
1165 let metadata_result = file_obj.metadata();
1167 assert!(
1168 metadata_result.is_ok(),
1169 "Should be able to get device file metadata"
1170 );
1171
1172 let mut read_buffer = [0u8; 10];
1174 let read_result = file_obj.read(&mut read_buffer);
1175 assert!(read_result.is_ok(), "Read operation should succeed");
1176
1177 let write_data = b"test";
1179 let write_result = file_obj.write(write_data);
1180 assert!(write_result.is_ok(), "Write operation should succeed");
1181
1182 let seek_result = file_obj.seek(crate::fs::SeekFrom::Start(0));
1184 assert!(seek_result.is_ok(), "Seek operation should succeed");
1185
1186 let truncate_result = file_obj.truncate(100);
1188 assert!(
1189 truncate_result.is_err(),
1190 "Truncate should fail for device files"
1191 );
1192 }
1193
1194 #[test_case]
1195 fn test_devfs_directory_operations() {
1196 use crate::device::char::mockchar::MockCharDevice;
1197
1198 let device_manager = DeviceManager::get_manager();
1200 let char_device = Arc::new(MockCharDevice::new("test_dir_ops"));
1201 let _device_id = device_manager
1202 .register_device_with_name("test_dir_ops".to_string(), char_device.clone());
1203
1204 let devfs = DevFS::new();
1206 let root = devfs.root_node();
1207
1208 let dir_file_result = devfs.open(&root, 0);
1210 assert!(
1211 dir_file_result.is_ok(),
1212 "Should be able to open directory in devfs"
1213 );
1214
1215 let dir_file = dir_file_result.unwrap();
1216
1217 let mut read_buffer = [0u8; 512]; let read_result = dir_file.read(&mut read_buffer);
1220 assert!(
1221 read_result.is_ok(),
1222 "Should be able to read directory contents"
1223 );
1224
1225 let bytes_read = read_result.unwrap();
1226 assert!(bytes_read > 0, "Should read some directory data");
1227
1228 let dir_entry = crate::fs::DirectoryEntry::parse(&read_buffer[..bytes_read]);
1230 assert!(
1231 dir_entry.is_some(),
1232 "Should be able to parse directory entry"
1233 );
1234
1235 let entry = dir_entry.unwrap();
1236 let name = entry.name_str().unwrap();
1237
1238 assert!(
1240 name == "." || name == ".." || name == "test_dir_ops",
1241 "Entry name should be '.', '..' or 'test_dir_ops', got: {}",
1242 name
1243 );
1244
1245 let seek_result = dir_file.seek(SeekFrom::Start(0));
1247 assert!(seek_result.is_ok(), "Should be able to seek in directory");
1248
1249 let metadata_result = dir_file.metadata();
1251 assert!(
1252 metadata_result.is_ok(),
1253 "Should be able to get directory metadata"
1254 );
1255
1256 let metadata = metadata_result.unwrap();
1257 assert_eq!(
1258 metadata.file_type,
1259 FileType::Directory,
1260 "Should be directory type"
1261 );
1262 }
1263}