kernel/fs/vfs_v2/drivers/
devfs.rs

1//! DevFS - Device filesystem implementation
2//!
3//! DevFS is a virtual filesystem that automatically exposes all devices
4//! registered in the global DeviceManager. When mounted (typically at /dev),
5//! it provides device files for all character and block devices that are
6//! currently registered with the kernel.
7//!
8//! ## Features
9//!
10//! - **Automatic Device Discovery**: Shows all devices from DeviceManager
11//! - **Dynamic Updates**: Reflects changes when devices are added/removed
12//! - **Device File Support**: Exposes character and block devices as device files
13//! - **Read-only Filesystem**: Device files cannot be created/deleted through VFS
14//!
15//! ## Usage
16//!
17//! ```rust
18//! // Mount devfs at /dev
19//! let vfs = VfsManager::new();
20//! let devfs = DevFS::new();
21//! vfs.mount(devfs, "/dev", 0)?;
22//!
23//! // Access device files
24//! let tty_file = vfs.open("/dev/tty0", O_RDWR)?;
25//! ```
26
27use 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
42/// DevFS - Device filesystem implementation
43///
44/// This filesystem automatically exposes all devices registered in the global
45/// DeviceManager as device files. It provides a virtual view of the system's
46/// devices, similar to /dev in Unix-like systems.
47pub struct DevFS {
48    /// Root directory node
49    root: RwLock<Arc<DevNode>>,
50    /// Filesystem name
51    name: String,
52}
53
54impl DevFS {
55    /// Create a new DevFS instance
56    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    /// Populate the filesystem with current devices from DeviceManager
68    fn populate_devices(&self) -> Result<(), FileSystemError> {
69        let device_manager = DeviceManager::get_manager();
70        let root = self.root.read();
71        
72        // Clear existing devices (for dynamic updates)
73        root.clear_children();
74        
75        // Get all devices that were registered with explicit names
76        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            // Only add char and block devices to devfs
82            match device_type {
83                DeviceType::Char | DeviceType::Block => {
84                    // Get the actual device ID from the name
85                    let device_id = device_manager.get_device_id_by_name(&device_name)
86                        .unwrap_or(0); // fallback to 0 if not found
87                    
88                    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, // Skip other device types
97                    };
98                    
99                    let device_node = Arc::new(DevNode::new_device_file(
100                        device_name.clone(),
101                        file_type,
102                        device_id as u64, // Use the device ID as file ID too
103                    ));
104                    
105                    // Set filesystem reference for the device node
106                    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                _ => {} // Skip non-device files
113            }
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        // Refresh devices on each root access to ensure up-to-date view
127        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        // Refresh devices before lookup to ensure up-to-date view
133        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        // Refresh devices before readdir to ensure up-to-date view
153        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    // DevFS is read-only - these operations are not supported
179    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
194/// A node in the DevFS filesystem
195pub struct DevNode {
196    /// Node name
197    name: String,
198    /// File type
199    file_type: FileType,
200    /// File ID
201    file_id: u64,
202    /// Child nodes (for directories)
203    children: RwLock<BTreeMap<String, Arc<DevNode>>>,
204    /// Reference to filesystem
205    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    /// Create a new directory node
222    pub fn new_directory(name: String) -> Self {
223        Self {
224            name,
225            file_type: FileType::Directory,
226            file_id: 0, // Root directory ID
227            children: RwLock::new(BTreeMap::new()),
228            filesystem: RwLock::new(None),
229        }
230    }
231
232    /// Create a new device file node
233    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    /// Set filesystem reference
244    pub fn set_filesystem(&self, fs: Weak<dyn FileSystemOperations>) {
245        *self.filesystem.write() = Some(fs);
246    }
247
248    /// Add a child node
249    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    /// Get a child by name
263    pub fn get_child(&self, name: &str) -> Option<Arc<DevNode>> {
264        let children = self.children.read();
265        children.get(name).cloned()
266    }
267
268    /// Clear all children (for dynamic updates)
269    pub fn clear_children(&self) {
270        let mut children = self.children.write();
271        children.clear();
272    }
273
274    /// Read directory contents
275    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        // Add "." entry (current directory)
287        entries.push(DirectoryEntryInternal {
288            name: ".".to_string(),
289            file_type: FileType::Directory,
290            file_id: self.file_id,
291        });
292
293        // Add ".." entry (parent directory)
294        // For DevFS root, parent is itself
295        entries.push(DirectoryEntryInternal {
296            name: "..".to_string(),
297            file_type: FileType::Directory,
298            file_id: self.file_id, // DevFS is always at root level, so parent is self
299        });
300
301        // Add actual child entries
302        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    /// Open the node as a file object
314    pub fn open(&self) -> Result<Arc<dyn FileObject>, FileSystemError> {
315        match self.file_type {
316            FileType::CharDevice(device_info) | FileType::BlockDevice(device_info) => {
317                // Create a device file object that can handle device operations
318                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                // Create a directory file object that can handle directory operations
326                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, // Device files have no size
347            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
369/// DevFS filesystem driver
370pub struct DevFSDriver;
371
372/// A file object for device files in DevFS
373/// 
374/// This struct provides a FileObject implementation that delegates
375/// device operations to the underlying device registered in DeviceManager.
376pub struct DevFileObject {
377    /// Reference to the DevNode
378    node: Arc<DevNode>,
379    /// Current file position (for seekable devices)
380    position: RwLock<u64>,
381    /// Device ID for lookup in DeviceManager
382    #[allow(dead_code)]
383    device_id: usize,
384    /// Device type
385    #[allow(dead_code)]
386    device_type: DeviceType,
387    /// Optional device guard for device files
388    device_guard: Option<Arc<dyn Device>>,
389}
390
391impl DevFileObject {
392    /// Create a new file object for device files
393    pub fn new(node: Arc<DevNode>, device_id: usize, device_type: DeviceType) -> Result<Self, FileSystemError> {
394        // Try to get the device from DeviceManager by ID
395        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    /// Read from the underlying device
415    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                        // For block devices, we read sectors using the request system
443                        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                                    // Copy the data back to the buffer
459                                    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    /// Write to the underlying device
495    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                // For device files, seeking from end is not well-defined
591                // Return current position
592                *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        // Device files cannot be truncated
606        Err(StreamError::from(FileSystemError::new(
607            FileSystemErrorKind::NotSupported,
608            "Cannot truncate device files"
609        )))
610    }
611}
612
613/// A file object for directories in DevFS
614/// 
615/// This struct provides a FileObject implementation for directories
616/// that allows reading directory entries as binary DirectoryEntry data.
617pub struct DevDirectoryObject {
618    /// Reference to the DevNode
619    node: Arc<DevNode>,
620    /// Current position in directory entries (entry index)
621    position: RwLock<usize>,
622}
623
624impl DevDirectoryObject {
625    /// Create a new directory file object
626    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        // Get all directory entries
637        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); // EOF
642        }
643        
644        // Convert the entry at current position to DirectoryEntry format
645        let internal_entry = &entries[position];
646        
647        // Create DirectoryEntryInternal with size field for DirectoryEntry::from_internal
648        let internal_with_size = crate::fs::DirectoryEntryInternal {
649            name: internal_entry.name.clone(),
650            file_type: internal_entry.file_type.clone(),
651            size: 0, // Device files have no meaningful size
652            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); // Buffer too small
661        }
662        
663        // Copy entry as bytes
664        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        // Move to next entry
674        *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        // Get directory entries to know the count
690        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        // DevFS doesn't use options, just create a new instance
744        self.create()
745    }
746}
747
748/// Register the DevFS driver with the filesystem driver manager
749fn 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        // Register a test device
781        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        // Check if we can read the directory (this should trigger device population)
789        let entries = devfs.readdir(&root).unwrap();
790        
791        // Note: Generic devices are not currently exposed in devfs (only Char/Block devices)
792        // So this test checks that the readdir operation works without error
793        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        // Try to lookup a non-existent device
802        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        // Register actual character and block devices
815        let device_manager = DeviceManager::get_manager();
816        
817        // Register a character device (TTY-like)
818        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        // Register a block device (disk-like)  
822        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        // Create devfs and verify devices appear
826        let devfs = DevFS::new();
827        let root = devfs.root_node();
828        
829        // Read directory contents
830        let entries = devfs.readdir(&root).unwrap();
831        
832        // Debug: print all entries to see what we actually have
833        let _unused_entries = &entries;
834        
835        // Should contain both our devices
836        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        // Test lookup functionality for character device
847        let tty0_result = devfs.lookup(&root, &"tty0".to_string());
848        assert!(tty0_result.is_ok(), "Should be able to lookup tty0");
849        
850        // Test lookup functionality for block device  
851        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        // Test that the DevFS driver is properly registered
858        let fs_driver_manager = get_fs_driver_manager();
859        
860        // Check if devfs driver is registered
861        assert!(fs_driver_manager.has_driver("devfs"), "DevFS driver should be registered");
862        
863        // Check driver type
864        let driver_type = fs_driver_manager.get_driver_type("devfs");
865        assert_eq!(driver_type, Some(FileSystemType::Device));
866        
867        // Test creating a devfs instance through the driver manager
868        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        // Test that create operations fail
882        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        // Test that remove operations fail
887        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        // Register a character device for testing
897        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        // Create devfs and lookup the device
902        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        // Test opening the device file
911        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        // Test basic FileObject operations
917        let metadata_result = file_obj.metadata();
918        assert!(metadata_result.is_ok(), "Should be able to get device file metadata");
919        
920        // Test read operation (should work even if device returns no data)
921        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        // Test write operation
926        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        // Test seek operation
931        let seek_result = file_obj.seek(crate::fs::SeekFrom::Start(0));
932        assert!(seek_result.is_ok(), "Seek operation should succeed");
933        
934        // Test truncate operation (should fail for device files)
935        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        // Register a character device for testing
944        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        // Create devfs
949        let devfs = DevFS::new();
950        let root = devfs.root_node();
951        
952        // Test opening directory
953        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        // Test reading directory contents (should return DirectoryEntry structs)
959        let mut read_buffer = [0u8; 512]; // Buffer for one directory entry
960        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        // Parse the directory entry
967        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        // Should be either "." or ".." or our test device
974        assert!(name == "." || name == ".." || name == "test_dir_ops", 
975               "Entry name should be '.', '..' or 'test_dir_ops', got: {}", name);
976        
977        // Test seek operations
978        let seek_result = dir_file.seek(SeekFrom::Start(0));
979        assert!(seek_result.is_ok(), "Should be able to seek in directory");
980        
981        // Test metadata
982        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}