1use alloc::{
28 boxed::Box, collections::BTreeMap, format, string::{String, ToString}, sync::{Arc, Weak}, vec::Vec
29};
30use spin::RwLock;
31use core::any::Any;
32
33use crate::{driver_initcall, fs::{
34 get_fs_driver_manager, DeviceFileInfo, FileMetadata, FileObject, FilePermission, FileSystemDriver,
35 FileSystemError, FileSystemErrorKind, FileSystemType, FileType, SeekFrom
36}};
37use crate::device::{manager::DeviceManager, DeviceType, Device};
38use crate::object::capability::{StreamOps, StreamError};
39
40use super::super::core::{VfsNode, FileSystemOperations, DirectoryEntryInternal};
41
42pub struct DevFS {
48 root: RwLock<Arc<DevNode>>,
50 name: String,
52}
53
54impl DevFS {
55 pub fn new() -> Arc<Self> {
57 let root = Arc::new(DevNode::new_directory("/".to_string()));
58 let fs = Arc::new(Self {
59 root: RwLock::new(Arc::clone(&root)),
60 name: "devfs".to_string(),
61 });
62 let fs_weak = Arc::downgrade(&(fs.clone() as Arc<dyn FileSystemOperations>));
63 root.set_filesystem(fs_weak);
64 fs
65 }
66
67 fn populate_devices(&self) -> Result<(), FileSystemError> {
69 let device_manager = DeviceManager::get_manager();
70 let root = self.root.read();
71
72 root.clear_children();
74
75 let named_devices = device_manager.get_named_devices();
77
78 for (device_name, device) in named_devices {
79 let device_type = device.device_type();
80
81 match device_type {
83 DeviceType::Char | DeviceType::Block => {
84 let device_id = device_manager.get_device_id_by_name(&device_name)
86 .unwrap_or(0); let device_file_info = DeviceFileInfo {
89 device_id,
90 device_type,
91 };
92
93 let file_type = match device_type {
94 DeviceType::Char => FileType::CharDevice(device_file_info),
95 DeviceType::Block => FileType::BlockDevice(device_file_info),
96 _ => continue, };
98
99 let device_node = Arc::new(DevNode::new_device_file(
100 device_name.clone(),
101 file_type,
102 device_id as u64, ));
104
105 if let Some(fs_ref) = root.filesystem() {
107 device_node.set_filesystem(fs_ref);
108 }
109
110 root.add_child(device_name, device_node)?;
111 }
112 _ => {} }
114 }
115
116 Ok(())
117 }
118}
119
120impl FileSystemOperations for DevFS {
121 fn name(&self) -> &str {
122 &self.name
123 }
124
125 fn root_node(&self) -> Arc<dyn VfsNode> {
126 let _ = self.populate_devices();
128 Arc::clone(&*self.root.read()) as Arc<dyn VfsNode>
129 }
130
131 fn lookup(&self, parent: &Arc<dyn VfsNode>, name: &String) -> Result<Arc<dyn VfsNode>, FileSystemError> {
132 let _ = self.populate_devices();
134
135 let dev_node = Arc::downcast::<DevNode>(parent.clone())
136 .map_err(|_| FileSystemError::new(
137 FileSystemErrorKind::NotSupported,
138 "Invalid node type for DevFS"
139 ))?;
140
141 if let Some(child) = dev_node.get_child(name) {
142 Ok(child as Arc<dyn VfsNode>)
143 } else {
144 Err(FileSystemError::new(
145 FileSystemErrorKind::NotFound,
146 format!("Device '{}' not found in devfs", name)
147 ))
148 }
149 }
150
151 fn readdir(&self, node: &Arc<dyn VfsNode>) -> Result<Vec<DirectoryEntryInternal>, FileSystemError> {
152 let _ = self.populate_devices();
154
155 let dev_node = Arc::downcast::<DevNode>(node.clone())
156 .map_err(|_| FileSystemError::new(
157 FileSystemErrorKind::NotSupported,
158 "Invalid node type for DevFS"
159 ))?;
160
161 dev_node.readdir()
162 }
163
164 fn open(&self, node: &Arc<dyn VfsNode>, _flags: u32) -> Result<Arc<dyn FileObject>, FileSystemError> {
165 let dev_node = Arc::downcast::<DevNode>(node.clone())
166 .map_err(|_| FileSystemError::new(
167 FileSystemErrorKind::NotSupported,
168 "Invalid node type for DevFS"
169 ))?;
170
171 dev_node.open()
172 }
173
174 fn is_read_only(&self) -> bool {
175 true
176 }
177
178 fn create(&self, _parent: &Arc<dyn VfsNode>, _name: &String, _file_type: FileType, _mode: u32) -> Result<Arc<dyn VfsNode>, FileSystemError> {
180 Err(FileSystemError::new(
181 FileSystemErrorKind::ReadOnly,
182 "DevFS is read-only: cannot create files"
183 ))
184 }
185
186 fn remove(&self, _parent: &Arc<dyn VfsNode>, _name: &String) -> Result<(), FileSystemError> {
187 Err(FileSystemError::new(
188 FileSystemErrorKind::ReadOnly,
189 "DevFS is read-only: cannot remove files"
190 ))
191 }
192}
193
194pub struct DevNode {
196 name: String,
198 file_type: FileType,
200 file_id: u64,
202 children: RwLock<BTreeMap<String, Arc<DevNode>>>,
204 filesystem: RwLock<Option<Weak<dyn FileSystemOperations>>>,
206}
207
208impl Clone for DevNode {
209 fn clone(&self) -> Self {
210 Self {
211 name: self.name.clone(),
212 file_type: self.file_type.clone(),
213 file_id: self.file_id,
214 children: RwLock::new(self.children.read().clone()),
215 filesystem: RwLock::new(self.filesystem.read().clone()),
216 }
217 }
218}
219
220impl DevNode {
221 pub fn new_directory(name: String) -> Self {
223 Self {
224 name,
225 file_type: FileType::Directory,
226 file_id: 0, children: RwLock::new(BTreeMap::new()),
228 filesystem: RwLock::new(None),
229 }
230 }
231
232 pub fn new_device_file(name: String, file_type: FileType, file_id: u64) -> Self {
234 Self {
235 name,
236 file_type,
237 file_id,
238 children: RwLock::new(BTreeMap::new()),
239 filesystem: RwLock::new(None),
240 }
241 }
242
243 pub fn set_filesystem(&self, fs: Weak<dyn FileSystemOperations>) {
245 *self.filesystem.write() = Some(fs);
246 }
247
248 pub fn add_child(&self, name: String, child: Arc<DevNode>) -> Result<(), FileSystemError> {
250 if self.file_type != FileType::Directory {
251 return Err(FileSystemError::new(
252 FileSystemErrorKind::NotADirectory,
253 "Cannot add child to non-directory node"
254 ));
255 }
256
257 let mut children = self.children.write();
258 children.insert(name, child);
259 Ok(())
260 }
261
262 pub fn get_child(&self, name: &str) -> Option<Arc<DevNode>> {
264 let children = self.children.read();
265 children.get(name).cloned()
266 }
267
268 pub fn clear_children(&self) {
270 let mut children = self.children.write();
271 children.clear();
272 }
273
274 pub fn readdir(&self) -> Result<Vec<DirectoryEntryInternal>, FileSystemError> {
276 if self.file_type != FileType::Directory {
277 return Err(FileSystemError::new(
278 FileSystemErrorKind::NotADirectory,
279 "Cannot read directory of non-directory node"
280 ));
281 }
282
283 let children = self.children.read();
284 let mut entries = Vec::new();
285
286 entries.push(DirectoryEntryInternal {
288 name: ".".to_string(),
289 file_type: FileType::Directory,
290 file_id: self.file_id,
291 });
292
293 entries.push(DirectoryEntryInternal {
296 name: "..".to_string(),
297 file_type: FileType::Directory,
298 file_id: self.file_id, });
300
301 for (name, child) in children.iter() {
303 entries.push(DirectoryEntryInternal {
304 name: name.clone(),
305 file_type: child.file_type.clone(),
306 file_id: child.file_id,
307 });
308 }
309
310 Ok(entries)
311 }
312
313 pub fn open(&self) -> Result<Arc<dyn FileObject>, FileSystemError> {
315 match self.file_type {
316 FileType::CharDevice(device_info) | FileType::BlockDevice(device_info) => {
317 Ok(Arc::new(DevFileObject::new(
319 Arc::new(self.clone()),
320 device_info.device_id,
321 device_info.device_type
322 )?))
323 }
324 FileType::Directory => {
325 Ok(Arc::new(DevDirectoryObject::new(Arc::new(self.clone()))))
327 }
328 _ => {
329 Err(FileSystemError::new(
330 FileSystemErrorKind::NotSupported,
331 "Unsupported file type in devfs"
332 ))
333 }
334 }
335 }
336}
337
338impl VfsNode for DevNode {
339 fn id(&self) -> u64 {
340 self.file_id
341 }
342
343 fn metadata(&self) -> Result<FileMetadata, FileSystemError> {
344 Ok(FileMetadata {
345 file_type: self.file_type.clone(),
346 size: 0, permissions: FilePermission {
348 read: true,
349 write: true,
350 execute: false,
351 },
352 created_time: 0,
353 modified_time: 0,
354 accessed_time: 0,
355 file_id: self.file_id,
356 link_count: 1,
357 })
358 }
359
360 fn filesystem(&self) -> Option<Weak<dyn FileSystemOperations>> {
361 self.filesystem.read().clone()
362 }
363
364 fn as_any(&self) -> &dyn Any {
365 self
366 }
367}
368
369pub struct DevFSDriver;
371
372pub struct DevFileObject {
377 node: Arc<DevNode>,
379 position: RwLock<u64>,
381 #[allow(dead_code)]
383 device_id: usize,
384 #[allow(dead_code)]
386 device_type: DeviceType,
387 device_guard: Option<Arc<dyn Device>>,
389}
390
391impl DevFileObject {
392 pub fn new(node: Arc<DevNode>, device_id: usize, device_type: DeviceType) -> Result<Self, FileSystemError> {
394 match DeviceManager::get_manager().get_device(device_id) {
396 Some(device_guard) => {
397 Ok(Self {
398 node,
399 position: RwLock::new(0),
400 device_id,
401 device_type,
402 device_guard: Some(device_guard),
403 })
404 }
405 None => {
406 Err(FileSystemError::new(
407 FileSystemErrorKind::DeviceError,
408 format!("Device with ID {} not found in DeviceManager", device_id)
409 ))
410 }
411 }
412 }
413
414 fn read_device(&self, buffer: &mut [u8]) -> Result<usize, FileSystemError> {
416 if let Some(ref device_guard) = self.device_guard {
417 let device_guard_ref = device_guard.as_ref();
418
419 match device_guard_ref.device_type() {
420 DeviceType::Char => {
421 if let Some(char_device) = device_guard_ref.as_char_device() {
422 let mut bytes_read = 0;
423 for byte in buffer.iter_mut() {
424 match char_device.read_byte() {
425 Some(b) => {
426 *byte = b;
427 bytes_read += 1;
428 },
429 None => break,
430 }
431 }
432 return Ok(bytes_read);
433 } else {
434 return Err(FileSystemError::new(
435 FileSystemErrorKind::DeviceError,
436 "Device does not support character operations"
437 ));
438 }
439 },
440 DeviceType::Block => {
441 if let Some(block_device) = device_guard_ref.as_block_device() {
442 let request = Box::new(crate::device::block::request::BlockIORequest {
444 request_type: crate::device::block::request::BlockIORequestType::Read,
445 sector: 0,
446 sector_count: 1,
447 head: 0,
448 cylinder: 0,
449 buffer: buffer.to_vec(),
450 });
451
452 block_device.enqueue_request(request);
453 let results = block_device.process_requests();
454
455 if let Some(result) = results.first() {
456 match &result.result {
457 Ok(_) => {
458 let bytes_to_copy = core::cmp::min(buffer.len(), result.request.buffer.len());
460 buffer[..bytes_to_copy].copy_from_slice(&result.request.buffer[..bytes_to_copy]);
461 return Ok(bytes_to_copy);
462 },
463 Err(e) => {
464 return Err(FileSystemError::new(
465 FileSystemErrorKind::IoError,
466 format!("Block device read failed: {}", e)
467 ));
468 }
469 }
470 }
471 return Ok(0);
472 } else {
473 return Err(FileSystemError::new(
474 FileSystemErrorKind::DeviceError,
475 "Device does not support block operations"
476 ));
477 }
478 },
479 _ => {
480 return Err(FileSystemError::new(
481 FileSystemErrorKind::DeviceError,
482 "Unsupported device type"
483 ));
484 }
485 }
486 } else {
487 Err(FileSystemError::new(
488 FileSystemErrorKind::DeviceError,
489 "No device guard available"
490 ))
491 }
492 }
493
494 fn write_device(&self, buffer: &[u8]) -> Result<usize, FileSystemError> {
496 if let Some(ref device_guard) = self.device_guard {
497 let device_guard_ref = device_guard.as_ref();
498
499 match device_guard_ref.device_type() {
500 DeviceType::Char => {
501 if let Some(char_device) = device_guard_ref.as_char_device() {
502 let mut bytes_written = 0;
503 for &byte in buffer {
504 match char_device.write_byte(byte) {
505 Ok(_) => bytes_written += 1,
506 Err(_) => break,
507 }
508 }
509 return Ok(bytes_written);
510 } else {
511 return Err(FileSystemError::new(
512 FileSystemErrorKind::DeviceError,
513 "Device does not support character operations"
514 ));
515 }
516 },
517 DeviceType::Block => {
518 if let Some(block_device) = device_guard_ref.as_block_device() {
519 let request = Box::new(crate::device::block::request::BlockIORequest {
520 request_type: crate::device::block::request::BlockIORequestType::Write,
521 sector: 0,
522 sector_count: 1,
523 head: 0,
524 cylinder: 0,
525 buffer: buffer.to_vec(),
526 });
527
528 block_device.enqueue_request(request);
529 let results = block_device.process_requests();
530
531 if let Some(result) = results.first() {
532 match &result.result {
533 Ok(_) => return Ok(buffer.len()),
534 Err(e) => {
535 return Err(FileSystemError::new(
536 FileSystemErrorKind::IoError,
537 format!("Block device write failed: {}", e)
538 ));
539 }
540 }
541 }
542 return Ok(0);
543 } else {
544 return Err(FileSystemError::new(
545 FileSystemErrorKind::DeviceError,
546 "Device does not support block operations"
547 ));
548 }
549 },
550 _ => {
551 return Err(FileSystemError::new(
552 FileSystemErrorKind::DeviceError,
553 "Unsupported device type"
554 ));
555 }
556 }
557 } else {
558 Err(FileSystemError::new(
559 FileSystemErrorKind::DeviceError,
560 "No device guard available"
561 ))
562 }
563 }
564}
565
566impl StreamOps for DevFileObject {
567 fn read(&self, buffer: &mut [u8]) -> Result<usize, StreamError> {
568 self.read_device(buffer).map_err(StreamError::from)
569 }
570
571 fn write(&self, buffer: &[u8]) -> Result<usize, StreamError> {
572 self.write_device(buffer).map_err(StreamError::from)
573 }
574}
575
576impl FileObject for DevFileObject {
577 fn seek(&self, whence: SeekFrom) -> Result<u64, StreamError> {
578 let mut position = self.position.write();
579
580 let new_pos = match whence {
581 SeekFrom::Start(offset) => offset,
582 SeekFrom::Current(offset) => {
583 if offset >= 0 {
584 *position + offset as u64
585 } else {
586 position.saturating_sub((-offset) as u64)
587 }
588 },
589 SeekFrom::End(_) => {
590 *position
593 }
594 };
595
596 *position = new_pos;
597 Ok(new_pos)
598 }
599
600 fn metadata(&self) -> Result<FileMetadata, StreamError> {
601 self.node.metadata().map_err(StreamError::from)
602 }
603
604 fn truncate(&self, _size: u64) -> Result<(), StreamError> {
605 Err(StreamError::from(FileSystemError::new(
607 FileSystemErrorKind::NotSupported,
608 "Cannot truncate device files"
609 )))
610 }
611}
612
613pub struct DevDirectoryObject {
618 node: Arc<DevNode>,
620 position: RwLock<usize>,
622}
623
624impl DevDirectoryObject {
625 pub fn new(node: Arc<DevNode>) -> Self {
627 Self {
628 node,
629 position: RwLock::new(0),
630 }
631 }
632}
633
634impl StreamOps for DevDirectoryObject {
635 fn read(&self, buffer: &mut [u8]) -> Result<usize, StreamError> {
636 let entries = self.node.readdir().map_err(StreamError::from)?;
638 let position = *self.position.read();
639
640 if position >= entries.len() {
641 return Ok(0); }
643
644 let internal_entry = &entries[position];
646
647 let internal_with_size = crate::fs::DirectoryEntryInternal {
649 name: internal_entry.name.clone(),
650 file_type: internal_entry.file_type.clone(),
651 size: 0, file_id: internal_entry.file_id,
653 metadata: None,
654 };
655
656 let dir_entry = crate::fs::DirectoryEntry::from_internal(&internal_with_size);
657 let entry_size = dir_entry.entry_size();
658
659 if buffer.len() < entry_size {
660 return Err(StreamError::InvalidArgument); }
662
663 let entry_bytes = unsafe {
665 core::slice::from_raw_parts(
666 &dir_entry as *const _ as *const u8,
667 entry_size
668 )
669 };
670
671 buffer[..entry_size].copy_from_slice(entry_bytes);
672
673 *self.position.write() += 1;
675
676 Ok(entry_size)
677 }
678
679 fn write(&self, _buffer: &[u8]) -> Result<usize, StreamError> {
680 Err(StreamError::from(FileSystemError::new(
681 FileSystemErrorKind::ReadOnly,
682 "Cannot write to directory in devfs"
683 )))
684 }
685}
686
687impl FileObject for DevDirectoryObject {
688 fn seek(&self, whence: SeekFrom) -> Result<u64, StreamError> {
689 let entries = self.node.readdir().map_err(StreamError::from)?;
691 let entry_count = entries.len() as u64;
692
693 let mut position = self.position.write();
694
695 let new_pos = match whence {
696 SeekFrom::Start(offset) => offset,
697 SeekFrom::Current(offset) => {
698 if offset >= 0 {
699 *position as u64 + offset as u64
700 } else {
701 (*position as u64).saturating_sub((-offset) as u64)
702 }
703 },
704 SeekFrom::End(offset) => {
705 if offset >= 0 {
706 entry_count + offset as u64
707 } else {
708 entry_count.saturating_sub((-offset) as u64)
709 }
710 }
711 };
712
713 *position = new_pos as usize;
714 Ok(new_pos)
715 }
716
717 fn metadata(&self) -> Result<FileMetadata, StreamError> {
718 self.node.metadata().map_err(StreamError::from)
719 }
720
721 fn truncate(&self, _size: u64) -> Result<(), StreamError> {
722 Err(StreamError::from(FileSystemError::new(
723 FileSystemErrorKind::ReadOnly,
724 "Cannot truncate directory in devfs"
725 )))
726 }
727}
728
729impl FileSystemDriver for DevFSDriver {
730 fn name(&self) -> &'static str {
731 "devfs"
732 }
733
734 fn filesystem_type(&self) -> FileSystemType {
735 FileSystemType::Device
736 }
737
738 fn create(&self) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
739 Ok(DevFS::new() as Arc<dyn FileSystemOperations>)
740 }
741
742 fn create_from_option_string(&self, _options: &str) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
743 self.create()
745 }
746}
747
748fn register_driver() {
750 let fs_driver_manager = get_fs_driver_manager();
751 fs_driver_manager.register_driver(Box::new(DevFSDriver));
752}
753
754driver_initcall!(register_driver);
755
756#[cfg(test)]
757mod tests {
758 use super::*;
759 use crate::device::{GenericDevice, manager::DeviceManager};
760 use alloc::sync::Arc;
761
762 #[test_case]
763 fn test_devfs_creation() {
764 let devfs = DevFS::new();
765 assert_eq!(devfs.name(), "devfs");
766 }
767
768 #[test_case]
769 fn test_devfs_root_access() {
770 let devfs = DevFS::new();
771 let root = devfs.root_node();
772 assert_eq!(root.id(), 0);
773
774 let metadata = root.metadata().unwrap();
775 assert_eq!(metadata.file_type, FileType::Directory);
776 }
777
778 #[test_case]
779 fn test_devfs_device_discovery() {
780 let device_manager = DeviceManager::get_manager();
782 let test_device = Arc::new(GenericDevice::new("test_devfs_device"));
783 let _device_id = device_manager.register_device_with_name("test_devfs_device".to_string(), test_device);
784
785 let devfs = DevFS::new();
786 let root = devfs.root_node();
787
788 let entries = devfs.readdir(&root).unwrap();
790
791 assert!(entries.len() == 0 || entries.len() > 0, "DevFS readdir should work without error");
794 }
795
796 #[test_case]
797 fn test_devfs_lookup() {
798 let devfs = DevFS::new();
799 let root = devfs.root_node();
800
801 let result = devfs.lookup(&root, &"nonexistent_device".to_string());
803 assert!(result.is_err(), "Lookup of non-existent device should fail");
804
805 let error = result.unwrap_err();
806 assert_eq!(error.kind, FileSystemErrorKind::NotFound);
807 }
808
809 #[test_case]
810 fn test_devfs_with_real_devices() {
811 use crate::device::char::mockchar::MockCharDevice;
812 use crate::device::block::mockblk::MockBlockDevice;
813
814 let device_manager = DeviceManager::get_manager();
816
817 let char_device = Arc::new(MockCharDevice::new("tty0"));
819 let _char_device_id = device_manager.register_device_with_name("tty0".to_string(), char_device.clone());
820
821 let block_device = Arc::new(MockBlockDevice::new("sda", 512, 1000));
823 let _block_device_id = device_manager.register_device_with_name("sda".to_string(), block_device.clone());
824
825 let devfs = DevFS::new();
827 let root = devfs.root_node();
828
829 let entries = devfs.readdir(&root).unwrap();
831
832 let _unused_entries = &entries;
834
835 let has_tty0 = entries.iter().any(|entry| {
837 entry.name == "tty0" && matches!(entry.file_type, FileType::CharDevice(_))
838 });
839 let has_sda = entries.iter().any(|entry| {
840 entry.name == "sda" && matches!(entry.file_type, FileType::BlockDevice(_))
841 });
842
843 assert!(has_tty0, "DevFS should contain tty0 character device");
844 assert!(has_sda, "DevFS should contain sda block device");
845
846 let tty0_result = devfs.lookup(&root, &"tty0".to_string());
848 assert!(tty0_result.is_ok(), "Should be able to lookup tty0");
849
850 let sda_result = devfs.lookup(&root, &"sda".to_string());
852 assert!(sda_result.is_ok(), "Should be able to lookup sda");
853 }
854
855 #[test_case]
856 fn test_devfs_driver_registration() {
857 let fs_driver_manager = get_fs_driver_manager();
859
860 assert!(fs_driver_manager.has_driver("devfs"), "DevFS driver should be registered");
862
863 let driver_type = fs_driver_manager.get_driver_type("devfs");
865 assert_eq!(driver_type, Some(FileSystemType::Device));
866
867 let devfs_result = fs_driver_manager.create_from_option_string("devfs", "");
869 assert!(devfs_result.is_ok(), "Should be able to create DevFS through driver manager");
870
871 let devfs_instance = devfs_result.unwrap();
872 assert_eq!(devfs_instance.name(), "devfs");
873 assert!(devfs_instance.is_read_only());
874 }
875
876 #[test_case]
877 fn test_devfs_readonly_operations() {
878 let devfs = DevFS::new();
879 let root = devfs.root_node();
880
881 let create_result = devfs.create(&root, &"test_file".to_string(), FileType::RegularFile, 0);
883 assert!(create_result.is_err());
884 assert_eq!(create_result.unwrap_err().kind, FileSystemErrorKind::ReadOnly);
885
886 let remove_result = devfs.remove(&root, &"test_file".to_string());
888 assert!(remove_result.is_err());
889 assert_eq!(remove_result.unwrap_err().kind, FileSystemErrorKind::ReadOnly);
890 }
891
892 #[test_case]
893 fn test_devfs_device_file_operations() {
894 use crate::device::char::mockchar::MockCharDevice;
895
896 let device_manager = DeviceManager::get_manager();
898 let char_device = Arc::new(MockCharDevice::new("test_char_dev"));
899 let _device_id = device_manager.register_device_with_name("test_char_dev".to_string(), char_device.clone());
900
901 let devfs = DevFS::new();
903 let root = devfs.root_node();
904
905 let device_node_result = devfs.lookup(&root, &"test_char_dev".to_string());
906 assert!(device_node_result.is_ok(), "Should be able to lookup character device");
907
908 let device_node = device_node_result.unwrap();
909
910 let file_result = devfs.open(&device_node, 0);
912 assert!(file_result.is_ok(), "Should be able to open character device file");
913
914 let file_obj = file_result.unwrap();
915
916 let metadata_result = file_obj.metadata();
918 assert!(metadata_result.is_ok(), "Should be able to get device file metadata");
919
920 let mut read_buffer = [0u8; 10];
922 let read_result = file_obj.read(&mut read_buffer);
923 assert!(read_result.is_ok(), "Read operation should succeed");
924
925 let write_data = b"test";
927 let write_result = file_obj.write(write_data);
928 assert!(write_result.is_ok(), "Write operation should succeed");
929
930 let seek_result = file_obj.seek(crate::fs::SeekFrom::Start(0));
932 assert!(seek_result.is_ok(), "Seek operation should succeed");
933
934 let truncate_result = file_obj.truncate(100);
936 assert!(truncate_result.is_err(), "Truncate should fail for device files");
937 }
938
939 #[test_case]
940 fn test_devfs_directory_operations() {
941 use crate::device::char::mockchar::MockCharDevice;
942
943 let device_manager = DeviceManager::get_manager();
945 let char_device = Arc::new(MockCharDevice::new("test_dir_ops"));
946 let _device_id = device_manager.register_device_with_name("test_dir_ops".to_string(), char_device.clone());
947
948 let devfs = DevFS::new();
950 let root = devfs.root_node();
951
952 let dir_file_result = devfs.open(&root, 0);
954 assert!(dir_file_result.is_ok(), "Should be able to open directory in devfs");
955
956 let dir_file = dir_file_result.unwrap();
957
958 let mut read_buffer = [0u8; 512]; let read_result = dir_file.read(&mut read_buffer);
961 assert!(read_result.is_ok(), "Should be able to read directory contents");
962
963 let bytes_read = read_result.unwrap();
964 assert!(bytes_read > 0, "Should read some directory data");
965
966 let dir_entry = crate::fs::DirectoryEntry::parse(&read_buffer[..bytes_read]);
968 assert!(dir_entry.is_some(), "Should be able to parse directory entry");
969
970 let entry = dir_entry.unwrap();
971 let name = entry.name_str().unwrap();
972
973 assert!(name == "." || name == ".." || name == "test_dir_ops",
975 "Entry name should be '.', '..' or 'test_dir_ops', got: {}", name);
976
977 let seek_result = dir_file.seek(SeekFrom::Start(0));
979 assert!(seek_result.is_ok(), "Should be able to seek in directory");
980
981 let metadata_result = dir_file.metadata();
983 assert!(metadata_result.is_ok(), "Should be able to get directory metadata");
984
985 let metadata = metadata_result.unwrap();
986 assert_eq!(metadata.file_type, FileType::Directory, "Should be directory type");
987 }
988}