kernel/fs/vfs_v2/drivers/tmpfs/
mod.rs

1//! TmpFS v2 - Memory-based filesystem implementation
2//!
3//! This is a complete rewrite of TmpFS using the new VFS v2 architecture.
4//! It implements FileSystemOperations directly and uses VfsNode for internal
5//! structure representation.
6
7use alloc::{
8    boxed::Box, collections::BTreeMap, format, string::{String, ToString}, sync::{Arc, Weak}, vec, vec::Vec
9};
10use spin::{rwlock::RwLock, Mutex};
11use core::{any::Any, fmt::Debug};
12
13use crate::{device::{Device, DeviceType}, driver_initcall, fs::{
14    get_fs_driver_manager, DeviceFileInfo, FileMetadata, FileObject, FilePermission, FileSystemDriver, FileSystemError, FileSystemErrorKind, FileType
15}};
16use crate::object::capability::{StreamOps, StreamError};
17use crate::device::manager::DeviceManager;
18
19use super::super::core::{VfsNode, FileSystemOperations, DirectoryEntryInternal};
20
21/// TmpFS v2 - New memory-based filesystem implementation
22///
23/// This struct implements an in-memory filesystem for VFS v2.
24/// It supports regular files, directories, and device nodes, with optional memory usage limits.
25/// The internal structure is based on `TmpNode` and uses locking for thread safety.
26///
27pub struct TmpFS {
28    /// Root directory node
29    root: RwLock<Arc<TmpNode>>,
30    /// Memory limit (0 = unlimited)
31    memory_limit: usize,
32    /// Current memory usage
33    current_memory: Mutex<usize>,
34    /// Next file ID generator
35    next_file_id: Mutex<u64>,
36    /// Filesystem name
37    name: String,
38}
39
40impl TmpFS {
41    /// Create a new TmpFS instance (two-phase initialization)
42    pub fn new(memory_limit: usize) -> Arc<Self> {
43        let root = Arc::new(TmpNode::new_directory("/".to_string(), 1));
44        let fs = Arc::new(Self {
45            root: RwLock::new(Arc::clone(&root)),
46            memory_limit,
47            current_memory: Mutex::new(0),
48            next_file_id: Mutex::new(2), // Start from 2, root is 1
49            name: "tmpfs_v2".to_string(),
50        });
51        let fs_weak = Arc::downgrade(&(fs.clone() as Arc<dyn FileSystemOperations>));
52        root.set_filesystem(fs_weak);
53        debug_assert!(root.filesystem().is_some(), "TmpFS root node's filesystem() is None after set_filesystem");
54        fs
55    }
56
57    /// VFS v2 driver registration API: create from option string
58    /// Example option: "mem=1048576" etc.
59    pub fn create_from_option_string(option: Option<&str>) -> Arc<dyn FileSystemOperations> {
60        let mut memory_limit = 0;
61        if let Some(opt) = option {
62            for part in opt.split(',') {
63                let part = part.trim();
64                if let Some(mem_str) = part.strip_prefix("mem=") {
65                    if let Ok(val) = mem_str.parse::<usize>() {
66                        memory_limit = val;
67                    }
68                }
69            }
70        }
71        TmpFS::new(memory_limit) as Arc<dyn FileSystemOperations>
72    }
73    
74    /// Generate next unique file ID
75    fn generate_file_id(&self) -> u64 {
76        let mut next_id = self.next_file_id.lock();
77        let id = *next_id;
78        *next_id += 1;
79        id
80    }
81    
82    /// Check memory limit
83    fn check_memory_limit(&self, additional_bytes: usize) -> Result<(), FileSystemError> {
84        if self.memory_limit == 0 {
85            return Ok(()); // Unlimited
86        }
87        
88        let current = *self.current_memory.lock();
89        if current + additional_bytes > self.memory_limit {
90            return Err(FileSystemError::new(
91                FileSystemErrorKind::NoSpace,
92                "TmpFS memory limit exceeded"
93            ));
94        }
95        
96        Ok(())
97    }
98    
99    /// Add to memory usage
100    fn add_memory_usage(&self, bytes: usize) {
101        if self.memory_limit > 0 {
102            *self.current_memory.lock() += bytes;
103        }
104    }
105    
106    /// Subtract from memory usage
107    fn subtract_memory_usage(&self, bytes: usize) {
108        if self.memory_limit > 0 {
109            let mut current = self.current_memory.lock();
110            *current = current.saturating_sub(bytes);
111        }
112    }
113}
114
115impl FileSystemOperations for TmpFS {
116    fn lookup(
117        &self,
118        parent_node: &Arc<dyn VfsNode>,
119        name: &String,
120    ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
121        // Downcast to TmpNode
122        let tmp_node = parent_node.as_any()
123            .downcast_ref::<TmpNode>()
124            .ok_or_else(|| FileSystemError::new(
125                FileSystemErrorKind::NotSupported,
126                "Invalid node type for TmpFS"
127            ))?;
128            
129        // Check if parent is a directory
130        if tmp_node.file_type() != FileType::Directory {
131            return Err(FileSystemError::new(
132                FileSystemErrorKind::NotADirectory,
133                "Parent is not a directory"
134            ));
135        }
136
137        // Handle special directory entries
138        match name.as_str() {
139            "." => {
140                // Current directory - return self
141                return Ok(Arc::clone(&parent_node));
142            }
143            ".." => {
144                // Parent directory - try to handle within filesystem
145                if let Some(parent_weak) = &tmp_node.parent() {
146                    if let Some(parent) = parent_weak.upgrade() {
147                        // crate::println!("TmpFS lookup: found parent node {:?}", parent);
148                        // Return parent node within this filesystem
149                        return Ok(parent as Arc<dyn VfsNode>);
150                    }
151                }
152            }
153            _ => {
154                // Regular lookup
155            }
156        }
157        
158        // Look up child in directory
159        let children = tmp_node.children.read();
160        if let Some(child_node) = children.get(name) {
161            Ok(Arc::clone(child_node) as Arc<dyn VfsNode>)
162        } else {
163            Err(FileSystemError::new(
164                FileSystemErrorKind::NotFound,
165                "File not found"
166            ))
167        }
168    }
169    
170    fn open(
171        &self,
172        node: &Arc<dyn VfsNode>,
173        _flags: u32,
174    ) -> Result<Arc<dyn FileObject>, FileSystemError> {
175        let tmp_node = Arc::downcast::<TmpNode>(node.clone())
176            .map_err(|_| FileSystemError::new(
177                FileSystemErrorKind::NotSupported,
178                "Invalid node type for TmpFS"
179            ))?;
180
181        let file_object = match tmp_node.file_type() {
182            FileType::RegularFile => TmpFileObject::new_regular(tmp_node),
183            FileType::Directory => TmpFileObject::new_directory(tmp_node),
184            FileType::CharDevice(info) | FileType::BlockDevice(info) => {
185                TmpFileObject::new_device(tmp_node, info)
186            }
187            _ => {
188                return Err(FileSystemError::new(
189                    FileSystemErrorKind::NotSupported,
190                    "Unsupported file type for open"
191                ));
192            }
193        };
194
195        Ok(Arc::new(file_object))
196    }
197    
198    fn create(&self,
199        parent_node: &Arc<dyn VfsNode>,
200        name: &String,
201        file_type: FileType,
202        _mode: u32,
203    ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
204        let tmp_parent = Arc::downcast::<TmpNode>(parent_node.clone())
205            .map_err(|_| FileSystemError::new(
206                FileSystemErrorKind::NotSupported,
207                "Invalid node type for TmpFS"
208            ))?;
209            
210        // Check if parent is a directory
211        if tmp_parent.file_type() != FileType::Directory {
212            return Err(FileSystemError::new(
213                FileSystemErrorKind::NotADirectory,
214                "Parent is not a directory"
215            ));
216        }
217        // Check if file already exists
218        {
219            let children = tmp_parent.children.read();
220            if children.contains_key(name) {
221                return Err(FileSystemError::new(
222                    FileSystemErrorKind::AlreadyExists,
223                    "File already exists"
224                ));
225            }
226        }
227        // Generate file ID
228        let file_id = self.generate_file_id();
229        let new_node = match file_type {
230            FileType::RegularFile => {
231                Arc::new(TmpNode::new_file(name.clone().to_string(), file_id))
232            }
233            FileType::Directory => {
234                Arc::new(TmpNode::new_directory(name.clone().to_string(), file_id))
235            }
236            FileType::SymbolicLink(target_path) => {
237                // Account for memory usage (target path length)
238                self.add_memory_usage(target_path.len());
239                Arc::new(TmpNode::new_symlink(name.clone().to_string(), target_path, file_id))
240            }
241            FileType::CharDevice(_) | FileType::BlockDevice(_) => {
242                Arc::new(TmpNode::new_device(name.clone().to_string(), file_type, file_id))
243            }
244            _ => {
245                return Err(FileSystemError::new(
246                    FileSystemErrorKind::NotSupported,
247                    "Unsupported file type for creation"
248                ));
249            }
250        };
251        // After creation, set the filesystem reference (always check if upgrade is possible)
252        let fs_ref = parent_node.filesystem()
253            .ok_or_else(|| FileSystemError::new(
254                FileSystemErrorKind::NotSupported,
255                "Parent node does not have a filesystem reference"
256            ))?;
257        if fs_ref.upgrade().is_none() {
258            return Err(FileSystemError::new(
259                FileSystemErrorKind::NotSupported,
260                "Parent node's filesystem reference is dead (cannot upgrade)"
261            ));
262        }
263        if let Some(tmp_node) = new_node.as_any().downcast_ref::<TmpNode>() {
264            tmp_node.set_filesystem(fs_ref);
265        }
266        // Add to parent directory
267        {
268            let mut children = tmp_parent.children.write();
269            new_node.set_parent(Arc::downgrade(&tmp_parent));
270            children.insert(name.clone(), Arc::clone(&new_node) as Arc<dyn VfsNode>);
271        }
272
273        Ok(new_node)
274    }
275
276    /// Create a hard link to an existing file
277    ///
278    /// This function creates a new directory entry (hard link) for an existing file.
279    /// Both the link and the target must be in the same filesystem.
280    /// The link count of the target file is incremented.
281    /// Returns the target node (the same inode as the original file).
282    fn create_hardlink(
283        &self,
284        link_parent: &Arc<dyn VfsNode>,
285        link_name: &String,
286        target_node: &Arc<dyn VfsNode>,
287    ) -> Result<Arc<dyn VfsNode>, FileSystemError> {
288        // Check that both parent and target are TmpNodes
289        let tmp_parent = link_parent.as_any()
290            .downcast_ref::<TmpNode>()
291            .ok_or_else(|| FileSystemError::new(
292                FileSystemErrorKind::NotSupported,
293                "Invalid parent node type for TmpFS"
294            ))?;
295            
296        let tmp_target = target_node.as_any()
297            .downcast_ref::<TmpNode>()
298            .ok_or_else(|| FileSystemError::new(
299                FileSystemErrorKind::NotSupported,
300                "Invalid target node type for TmpFS"
301            ))?;
302        
303        // Check that parent is a directory
304        if tmp_parent.file_type() != FileType::Directory {
305            return Err(FileSystemError::new(
306                FileSystemErrorKind::NotADirectory,
307                "Parent is not a directory"
308            ));
309        }
310        
311        // Check that target is a regular file (no directory hard links)
312        if tmp_target.file_type() != FileType::RegularFile {
313            return Err(FileSystemError::new(
314                FileSystemErrorKind::InvalidOperation,
315                "Cannot create hard link to non-regular file"
316            ));
317        }
318        
319        // Check if link name already exists
320        {
321            let children = tmp_parent.children.read();
322            if children.contains_key(link_name) {
323                return Err(FileSystemError::new(
324                    FileSystemErrorKind::FileExists,
325                    "Link name already exists"
326                ));
327            }
328        }
329        
330        // For TmpFS, hard links are just additional references to the same TmpNode
331        // Update the link count in metadata
332        {
333            let mut metadata = tmp_target.metadata.write();
334            metadata.link_count += 1;
335        }
336        
337        // Add the target node to the parent directory under the new name
338        {
339            let mut children = tmp_parent.children.write();
340            children.insert(link_name.clone(), Arc::clone(target_node));
341        }
342        
343        // Return the same target node (hard link shares the same inode)
344        Ok(Arc::clone(target_node))
345    }
346
347    
348    fn remove(
349        &self,
350        parent_node: &Arc<dyn VfsNode>,
351        name: &String,
352    ) -> Result<(), FileSystemError> {
353        let tmp_parent = parent_node.as_any()
354            .downcast_ref::<TmpNode>()
355            .ok_or_else(|| FileSystemError::new(
356                FileSystemErrorKind::NotSupported,
357                "Invalid node type for TmpFS"
358            ))?;
359            
360        // Check if parent is a directory
361        if tmp_parent.file_type() != FileType::Directory {
362            return Err(FileSystemError::new(
363                FileSystemErrorKind::NotADirectory,
364                "Parent is not a directory"
365            ));
366        }
367        
368        // Remove from parent directory
369        let mut children = tmp_parent.children.write();
370        if let Some(removed_node) = children.get(name) {
371            // If it's a directory, check if it's empty first
372            if let Some(tmp_node) = removed_node.as_any().downcast_ref::<TmpNode>() {
373                if tmp_node.file_type() == FileType::Directory {
374                    let child_children = tmp_node.children.read();
375                    if !child_children.is_empty() {
376                        return Err(FileSystemError::new(
377                            FileSystemErrorKind::DirectoryNotEmpty,
378                            "Directory not empty"
379                        ));
380                    }
381                }
382                
383                // Update memory usage for regular files and symbolic links
384                match tmp_node.file_type() {
385                    FileType::RegularFile | FileType::SymbolicLink(_) => {
386                        let content = tmp_node.content.read();
387                        self.subtract_memory_usage(content.len());
388                    },
389                    _ => {}
390                }
391            }
392        }
393        
394        // Now remove the node
395        children.remove(name)
396            .ok_or_else(|| FileSystemError::new(
397                FileSystemErrorKind::NotFound,
398                "File not found"
399            ))?;
400        
401        Ok(())
402    }
403    
404    fn readdir(
405        &self,
406        node: &Arc<dyn VfsNode>,
407    ) -> Result<Vec<DirectoryEntryInternal>, FileSystemError> {
408        let tmp_node = node.as_any()
409            .downcast_ref::<TmpNode>()
410            .ok_or_else(|| FileSystemError::new(
411                FileSystemErrorKind::NotSupported,
412                "Invalid node type for TmpFS"
413            ))?;
414            
415        // Check if it's a directory
416        if tmp_node.file_type() != FileType::Directory {
417            return Err(FileSystemError::new(
418                FileSystemErrorKind::NotADirectory,
419                "Not a directory"
420            ));
421        }
422        
423        let mut entries = Vec::new();
424        let children = tmp_node.children.read();
425        
426        for (name, child_node) in children.iter() {
427            if let Some(child_tmp_node) = child_node.as_any().downcast_ref::<TmpNode>() {
428                let metadata = child_tmp_node.metadata.read();
429                entries.push(DirectoryEntryInternal {
430                    name: name.clone(),
431                    file_type: child_tmp_node.file_type.read().clone(),
432                    file_id: metadata.file_id,
433                });
434            }
435        }
436        
437        Ok(entries)
438    }
439    
440    fn root_node(&self) -> Arc<dyn VfsNode> {
441        Arc::clone(&*self.root.read()) as Arc<dyn VfsNode>
442    }
443    
444    fn name(&self) -> &str {
445        &self.name
446    }
447}
448
449/// TmpNode represents a file, directory, or device node in TmpFS.
450///
451/// Each node contains metadata, content (for files), children (for directories),
452/// and references to its parent and filesystem. All fields are protected by locks for thread safety.
453pub struct TmpNode {
454    /// File name
455    name: RwLock<String>,
456    /// File type
457    file_type: RwLock<FileType>,
458    /// File metadata
459    metadata: RwLock<FileMetadata>,
460    /// File content (for regular files)
461    content: RwLock<Vec<u8>>,
462    /// Child nodes (for directories)
463    children: RwLock<BTreeMap<String, Arc<dyn VfsNode>>>,
464    /// Parent node (weak reference to avoid cycles)
465    parent: RwLock<Option<Weak<TmpNode>>>,
466    /// Reference to filesystem (Weak<dyn FileSystemOperations>)
467    filesystem: RwLock<Option<Weak<dyn FileSystemOperations>>>,
468}
469
470impl Debug for TmpNode {
471    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
472        f.debug_struct("TmpNode")
473            .field("name", &self.name.read())
474            .field("file_type", &self.file_type.read())
475            .field("metadata", &self.metadata.read())
476            .field("parent", &self.parent.read().as_ref().map(|p| p.strong_count()))
477            .finish()
478    }
479}
480
481impl TmpNode {
482    /// Create a new regular file node
483    pub fn new_file(name: String, file_id: u64) -> Self {
484        Self {
485            name: RwLock::new(name),
486            file_type: RwLock::new(FileType::RegularFile),
487            metadata: RwLock::new(FileMetadata {
488                file_type: FileType::RegularFile,
489                size: 0,
490                permissions: FilePermission {
491                    read: true,
492                    write: true,
493                    execute: false,
494                },
495                created_time: 0, // TODO: actual timestamp
496                modified_time: 0,
497                accessed_time: 0,
498                file_id,
499                link_count: 1,
500            }),
501            content: RwLock::new(Vec::new()),
502            children: RwLock::new(BTreeMap::new()),
503            parent: RwLock::new(None), // No parent initially
504            filesystem: RwLock::new(None),
505        }
506    }
507    
508    /// Create a new directory node
509    pub fn new_directory(name: String, file_id: u64) -> Self {
510        Self {
511            name: RwLock::new(name),
512            file_type: RwLock::new(FileType::Directory),
513            metadata: RwLock::new(FileMetadata {
514                file_type: FileType::Directory,
515                size: 0,
516                permissions: FilePermission {
517                    read: true,
518                    write: true,
519                    execute: true,
520                },
521                created_time: 0,
522                modified_time: 0,
523                accessed_time: 0,
524                file_id,
525                link_count: 1,
526            }),
527            content: RwLock::new(Vec::new()),
528            children: RwLock::new(BTreeMap::new()),
529            parent: RwLock::new(None), // No parent initially
530            filesystem: RwLock::new(None),
531        }
532    }
533    
534    /// Create a new device file node
535    pub fn new_device(name: String, file_type: FileType, file_id: u64) -> Self {
536        Self {
537            name: RwLock::new(name),
538            file_type: RwLock::new(file_type.clone()),
539            metadata: RwLock::new(FileMetadata {
540                file_type,
541                size: 0,
542                permissions: FilePermission {
543                    read: true,
544                    write: true,
545                    execute: false,
546                },
547                created_time: 0,
548                modified_time: 0,
549                accessed_time: 0,
550                file_id,
551                link_count: 1,
552            }),
553            content: RwLock::new(Vec::new()),
554            children: RwLock::new(BTreeMap::new()),
555            parent: RwLock::new(None), // No parent initially
556            filesystem: RwLock::new(None),
557        }
558    }
559    
560    /// Create a new symbolic link node
561    pub fn new_symlink(name: String, target: String, file_id: u64) -> Self {
562        Self {
563            name: RwLock::new(name),
564            file_type: RwLock::new(FileType::SymbolicLink(target.clone())),
565            metadata: RwLock::new(FileMetadata {
566                file_type: FileType::SymbolicLink(target.clone()),
567                size: target.len(),
568                permissions: FilePermission {
569                    read: true,
570                    write: true,
571                    execute: false,
572                },
573                created_time: 0, // TODO: actual timestamp
574                modified_time: 0,
575                accessed_time: 0,
576                file_id,
577                link_count: 1,
578            }),
579            // Store symlink target in content as UTF-8 bytes
580            content: RwLock::new(target.into_bytes()),
581            children: RwLock::new(BTreeMap::new()),
582            parent: RwLock::new(None), // No parent initially
583            filesystem: RwLock::new(None),
584        }
585    }
586    
587    /// Set the filesystem reference for this node
588    pub fn set_filesystem(&self, fs: Weak<dyn FileSystemOperations>) {
589        *self.filesystem.write() = Some(fs);
590    }
591    
592    /// Update file size in metadata
593    pub fn update_size(&self, new_size: u64) {
594        let mut metadata = self.metadata.write();
595        metadata.size = new_size as usize;
596        metadata.modified_time = 0; // TODO: actual timestamp
597    }
598    
599    /// Set parent reference for this node
600    pub fn set_parent(&self, parent: Weak<TmpNode>) {
601        self.parent.write().replace(parent);
602    }
603    
604    /// Check if this node is the root of the filesystem
605    pub fn is_filesystem_root(&self) -> bool {
606        self.parent.read().is_none()
607    }
608
609    /// Get the file name
610    pub fn name(&self) -> String {
611        self.name.read().clone()
612    }
613
614    /// Get the file type
615    pub fn file_type(&self) -> FileType {
616        self.file_type.read().clone()
617    }
618
619    /// Get the filesystem reference
620    pub fn filesystem(&self) -> Option<Weak<dyn FileSystemOperations>> {
621        self.filesystem.read().clone()
622    }
623
624    /// Get the parent node
625    pub fn parent(&self) -> Option<Weak<TmpNode>> {
626        self.parent.read().clone()
627    }
628}
629
630impl VfsNode for TmpNode {
631    fn id(&self) -> u64 {
632        self.metadata.read().file_id
633    }
634    
635    fn filesystem(&self) -> Option<Weak<dyn FileSystemOperations>> {
636        self.filesystem.read().clone()
637    }
638    
639    fn metadata(&self) -> Result<FileMetadata, FileSystemError> {
640        Ok(self.metadata.read().clone())
641    }
642    
643    fn as_any(&self) -> &dyn Any {
644        self
645    }
646    
647    fn read_link(&self) -> Result<String, FileSystemError> {
648        // Check if this is actually a symbolic link and return target
649        match &self.file_type() {
650            FileType::SymbolicLink(target) => Ok(target.clone()),
651            _ => Err(FileSystemError::new(
652                FileSystemErrorKind::NotSupported,
653                "Not a symbolic link"
654            ))
655        }
656    }
657}
658
659/// File object for TmpFS operations
660///
661/// TmpFileObject represents an open file or directory in TmpFS.
662///
663/// It maintains the current file position and, for device files, an optional device guard.
664pub struct TmpFileObject {
665    /// Reference to the TmpNode
666    node: Arc<TmpNode>,
667    
668    /// Current file position
669    position: RwLock<u64>,
670    
671    /// Optional device guard for device files
672    device_guard: Option<Arc<dyn Device>>,
673}
674
675impl TmpFileObject {
676    /// Create a new file object for regular files
677    pub fn new_regular(node: Arc<TmpNode>) -> Self {
678        Self {
679            node,
680            position: RwLock::new(0),
681            device_guard: None,
682        }
683    }
684    
685    /// Create a new file object for directories
686    pub fn new_directory(node: Arc<TmpNode>) -> Self {
687        Self {
688            node,
689            position: RwLock::new(0),
690            device_guard: None,
691        }
692    }
693    
694    /// Create a new file object for device files
695    pub fn new_device(node: Arc<TmpNode>, info: DeviceFileInfo) -> Self {
696        // Try to borrow the device from DeviceManager
697        match DeviceManager::get_manager().get_device(info.device_id) {
698            Some(device_guard) => {
699                Self {
700                    node,
701                    position: RwLock::new(0),
702                    device_guard: Some(device_guard),
703                }
704            },
705            None => {
706                // If borrowing fails, return an error
707                panic!("Failed to borrow device {}", info.device_id);
708            }
709        }
710    }
711                        
712    fn read_device(&self, buffer: &mut [u8]) -> Result<usize, FileSystemError> {
713        if let Some(ref device_guard) = self.device_guard {
714            let device_guard_ref = device_guard.as_ref();
715            
716            match device_guard_ref.device_type() {
717                DeviceType::Char => {
718                    if let Some(char_device) = device_guard_ref.as_char_device() {
719                        let mut bytes_read = 0;
720                        for byte in buffer.iter_mut() {
721                            match char_device.read_byte() {
722                                Some(b) => {
723                                    *byte = b;
724                                    bytes_read += 1;
725                                },
726                                None => break,
727                            }
728                        }
729                        return Ok(bytes_read);
730                    } else {
731                        return Err(FileSystemError {
732                            kind: FileSystemErrorKind::NotSupported,
733                            message: "Device is not a character device".to_string(),
734                        });
735                    }
736                },
737                DeviceType::Block => {
738                    if let Some(block_device) = device_guard_ref.as_block_device() {
739                        // For block devices, we can read a single sector
740                        let request = Box::new(crate::device::block::request::BlockIORequest {
741                            request_type: crate::device::block::request::BlockIORequestType::Read,
742                            sector: 0,
743                            sector_count: 1,
744                            head: 0,
745                            cylinder: 0,
746                            buffer: buffer.to_vec(),
747                        });
748                        
749                        block_device.enqueue_request(request);
750                        let results = block_device.process_requests();
751                        
752                        if let Some(result) = results.first() {
753                            match &result.result {
754                                Ok(_) => return Ok(buffer.len()),
755                                Err(e) => {
756                                    return Err(FileSystemError {
757                                        kind: FileSystemErrorKind::IoError,
758                                        message: format!("Block device read failed: {}", e),
759                                    });
760                                }
761                            }
762                        }
763                        return Ok(0);
764                    } else {
765                        return Err(FileSystemError {
766                            kind: FileSystemErrorKind::NotSupported,
767                            message: "Device is not a block device".to_string(),
768                        });
769                    }
770                },
771                _ => {
772                    return Err(FileSystemError {
773                        kind: FileSystemErrorKind::NotSupported,
774                        message: "Unsupported device type".to_string(),
775                    });
776                }
777            }
778        }
779
780        Err(FileSystemError {
781            kind: FileSystemErrorKind::NotSupported,
782            message: "No device guard available".to_string(),
783        })
784    }
785
786    fn read_regular_file(&self, buffer: &mut [u8]) -> Result<usize, FileSystemError> {
787        let mut position = self.position.write();
788        
789        // Use the direct node reference instead of finding it by path
790        
791        let content_guard = self.node.content.write();
792        // self.node.update_access_time();
793
794        if *position as usize >= content_guard.len() {
795            return Ok(0); // EOF
796        }
797        
798        let available = content_guard.len() - *position as usize;
799        let to_read = buffer.len().min(available);
800        
801        buffer[..to_read].copy_from_slice(&content_guard[*position as usize..*position as usize + to_read]);
802        *position += to_read as u64;
803        
804        Ok(to_read)
805    }
806
807    fn write_device(&self, buffer: &[u8]) -> Result<usize, FileSystemError> {
808        if let Some(ref device_guard) = self.device_guard {
809            let device_guard_ref = device_guard.as_ref();
810            
811            match device_guard_ref.device_type() {
812                DeviceType::Char => {
813                    if let Some(char_device) = device_guard_ref.as_char_device() {
814                        let mut bytes_written = 0;
815                        for &byte in buffer {
816                            match char_device.write_byte(byte) {
817                                Ok(_) => bytes_written += 1,
818                                Err(_) => break,
819                            }
820                        }
821                        return Ok(bytes_written);
822                    } else {
823                        return Err(FileSystemError {
824                            kind: FileSystemErrorKind::NotSupported,
825                            message: "Device is not a character device".to_string(),
826                        });
827                    }
828                },
829                DeviceType::Block => {
830                    if let Some(block_device) = device_guard_ref.as_block_device() {
831                        let request = Box::new(crate::device::block::request::BlockIORequest {
832                            request_type: crate::device::block::request::BlockIORequestType::Write,
833                            sector: 0,
834                            sector_count: 1,
835                            head: 0,
836                            cylinder: 0,
837                            buffer: buffer.to_vec(),
838                        });
839                        
840                        block_device.enqueue_request(request);
841                        let results = block_device.process_requests();
842                        
843                        if let Some(result) = results.first() {
844                            match &result.result {
845                                Ok(_) => return Ok(buffer.len()),
846                                Err(e) => {
847                                    return Err(FileSystemError {
848                                        kind: FileSystemErrorKind::IoError,
849                                        message: format!("Block device write failed: {}", e),
850                                    });
851                                }
852                            }
853                        }
854                        return Ok(0);
855                    } else {
856                        return Err(FileSystemError {
857                            kind: FileSystemErrorKind::NotSupported,
858                            message: "Device is not a block device".to_string(),
859                        });
860                    }
861                },
862                _ => {
863                    return Err(FileSystemError {
864                        kind: FileSystemErrorKind::NotSupported,
865                        message: "Unsupported device type".to_string(),
866                    });
867                }
868            }
869        } else {
870            Err(FileSystemError {
871                kind: FileSystemErrorKind::NotSupported,
872                message: "No device guard available".to_string(),
873            })
874        }
875    }
876
877    fn write_regular_file(&self, buffer: &[u8]) -> Result<usize, FileSystemError> {
878        let mut position = self.position.write();
879        
880        // Use the direct node reference instead of finding it by path
881        let mut content_guard = self.node.content.write();
882        let _old_size = content_guard.len();
883        let new_position = *position as usize + buffer.len();
884        
885        // Expand file if necessary
886        if new_position > content_guard.len() {
887            content_guard.resize(new_position, 0);
888        }
889        
890        // Write data
891        content_guard[*position as usize..new_position].copy_from_slice(buffer);
892        let new_size = content_guard.len();
893        
894        // Update metadata
895        self.node.update_size(new_size as u64);
896        
897        // let size_increase = new_size.saturating_sub(old_size);
898        *position += buffer.len() as u64;
899        Ok(buffer.len())
900    }
901}
902
903impl StreamOps for TmpFileObject {
904    fn read(&self, buffer: &mut [u8]) -> Result<usize, StreamError> {
905        match self.node.file_type() {
906            FileType::RegularFile => {
907                self.read_regular_file(buffer)
908                    .map_err(StreamError::from)
909            }
910            FileType::Directory => {
911                // For directories, return entries in struct format
912                let node = self.node.clone();
913                // We need to reconstruct the path from the node structure
914                // Since we don't have path stored, use the readdir logic directly
915                
916                // Create a vector to store all entries including "." and ".."
917                // Add "." entry (current directory)
918                let current_metadata = node.metadata.read();
919                let mut all_entries = vec![crate::fs::DirectoryEntryInternal {
920                    name: ".".to_string(),
921                    file_type: FileType::Directory,
922                    size: current_metadata.size,
923                    file_id: current_metadata.file_id,
924                    metadata: Some(current_metadata.clone()),
925                }];
926                
927                // Add ".." entry (parent directory) - simplified to point to self for now
928                all_entries.push(crate::fs::DirectoryEntryInternal {
929                    name: "..".to_string(),
930                    file_type: FileType::Directory,
931                    size: current_metadata.size,
932                    file_id: current_metadata.file_id,
933                    metadata: Some(current_metadata.clone()),
934                });
935                
936                // Add regular directory entries and sort by file_id
937                let children = node.children.read();
938                let mut regular_entries = Vec::new();
939                for (name, child) in children.iter() {
940                    let metadata = child.metadata().unwrap();
941                    regular_entries.push(crate::fs::DirectoryEntryInternal {
942                        name: name.clone(),
943                        file_type: child.file_type().unwrap().clone(),
944                        size: metadata.size,
945                        file_id: metadata.file_id,
946                        metadata: Some(metadata.clone()),
947                    });
948                }
949                
950                // Sort regular entries by file_id (ascending order)
951                regular_entries.sort_by_key(|entry| entry.file_id);
952                
953                // Append sorted regular entries to the result
954                all_entries.extend(regular_entries);
955                
956                // position is the entry index
957                let position = *self.position.read() as usize;
958                
959                if position >= all_entries.len() {
960                    return Ok(0); // EOF
961                }
962                
963                // Get current entry (already sorted)
964                let internal_entry = &all_entries[position];
965                
966                // Convert to binary format
967                let dir_entry = crate::fs::DirectoryEntry::from_internal(internal_entry);
968                
969                // Calculate actual entry size
970                let entry_size = dir_entry.entry_size();
971                
972                // Check buffer size
973                if buffer.len() < entry_size {
974                    return Err(StreamError::InvalidArgument); // Buffer too small
975                }
976                
977                // Treat struct as byte array
978                let entry_bytes = unsafe {
979                    core::slice::from_raw_parts(
980                        &dir_entry as *const _ as *const u8,
981                        entry_size
982                    )
983                };
984                
985                // Copy to buffer
986                buffer[..entry_size].copy_from_slice(entry_bytes);
987                
988                // Move to next entry
989                *self.position.write() += 1;
990                
991                Ok(entry_size)
992            },
993            FileType::CharDevice(_) | FileType::BlockDevice(_) => {
994                self.read_device(buffer)
995                    .map_err(StreamError::from)
996            }
997            _ => Err(StreamError::NotSupported)
998        }
999    }
1000    
1001    fn write(&self, buffer: &[u8]) -> Result<usize, StreamError> {
1002        match self.node.file_type() {
1003            FileType::RegularFile => {
1004                self.write_regular_file(buffer).map_err(StreamError::from)
1005            }
1006            FileType::Directory => {
1007                Err(StreamError::from(FileSystemError::new(
1008                    FileSystemErrorKind::IsADirectory,
1009                    "Cannot write to directory"
1010                )))
1011            }
1012            FileType::CharDevice(_) | FileType::BlockDevice(_) => {
1013                self.write_device(buffer).map_err(StreamError::from)
1014            }
1015            _ => Err(StreamError::NotSupported)
1016        }
1017    }
1018}
1019
1020impl FileObject for TmpFileObject {
1021    fn seek(&self, pos: crate::fs::SeekFrom) -> Result<u64, StreamError> {
1022        use crate::fs::SeekFrom;
1023        
1024        let mut position = self.position.write();
1025        let content = self.node.content.read();
1026        let file_size = content.len() as u64;
1027        
1028        let new_pos = match pos {
1029            SeekFrom::Start(offset) => {
1030                if offset <= file_size {
1031                    offset
1032                } else {
1033                    return Err(StreamError::from(FileSystemError::new(
1034                        FileSystemErrorKind::NotSupported,
1035                        "Seek offset beyond EOF"
1036                    )));
1037                }
1038            }
1039            SeekFrom::End(offset) => {
1040                if offset >= 0 {
1041                    file_size + offset as u64
1042                } else {
1043                    file_size.saturating_sub((-offset) as u64)
1044                }
1045            }
1046            SeekFrom::Current(offset) => {
1047                if offset >= 0 {
1048                    *position + offset as u64
1049                } else {
1050                    position.saturating_sub((-offset) as u64)
1051                }
1052            }
1053        };
1054        
1055        *position = new_pos;
1056        Ok(new_pos)
1057    }
1058    
1059    fn metadata(&self) -> Result<FileMetadata, StreamError> {
1060        self.node.metadata().map_err(StreamError::from)
1061    }
1062    
1063    fn truncate(&self, size: u64) -> Result<(), StreamError> {
1064        if self.node.file_type() != FileType::RegularFile {
1065            return Err(StreamError::from(FileSystemError::new(
1066                FileSystemErrorKind::IsADirectory,
1067                "Cannot truncate non-regular file"
1068            )));
1069        }
1070        
1071        let mut content = self.node.content.write();
1072        let old_size = content.len();
1073        let new_size = size as usize;
1074        
1075        if new_size > old_size {
1076            // Expand with zeros
1077            content.resize(new_size, 0);
1078        } else if new_size < old_size {
1079            // Truncate
1080            content.truncate(new_size);
1081        }
1082        
1083        // Update metadata
1084        self.node.update_size(size);
1085        
1086        Ok(())
1087    }
1088}
1089
1090pub struct TmpFSDriver;
1091
1092impl FileSystemDriver for TmpFSDriver {
1093    
1094    fn filesystem_type(&self) -> crate::fs::FileSystemType {
1095        crate::fs::FileSystemType::Virtual
1096    }
1097    
1098    fn create_from_memory(&self, _memory_area: &crate::vm::vmem::MemoryArea) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
1099        Ok(TmpFS::new(0) as Arc<dyn FileSystemOperations>)
1100    }
1101    
1102    fn create_from_params(&self, _params: &dyn crate::fs::params::FileSystemParams) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
1103        Ok(TmpFS::create_from_option_string(None))
1104    }
1105
1106    fn create_from_option_string(&self, options: &str) -> Result<Arc<dyn FileSystemOperations>, FileSystemError> {
1107        // Parse tmpfs options (e.g., "size=64M")
1108        let memory_limit = parse_tmpfs_size_option(options).unwrap_or(64 * 1024 * 1024); // Default 64MB
1109        Ok(TmpFS::new(memory_limit))
1110    }
1111    
1112    fn name(&self) -> &'static str {
1113        "tmpfs"
1114    }
1115}
1116
1117/// Parse tmpfs size option from option string
1118/// 
1119/// Parses size option in the format "size=64M", "size=1G", etc.
1120/// Returns the size in bytes, or None if no valid size option is found.
1121fn parse_tmpfs_size_option(options: &str) -> Option<usize> {
1122    for option in options.split(',') {
1123        if let Some(size_str) = option.strip_prefix("size=") {
1124            // Parse size with suffix (K, M, G)
1125            let size_str = size_str.trim();
1126            if size_str.is_empty() {
1127                continue;
1128            }
1129            
1130            let (number_part, multiplier) = if size_str.ends_with('K') || size_str.ends_with('k') {
1131                (&size_str[..size_str.len()-1], 1024)
1132            } else if size_str.ends_with('M') || size_str.ends_with('m') {
1133                (&size_str[..size_str.len()-1], 1024 * 1024)
1134            } else if size_str.ends_with('G') || size_str.ends_with('g') {
1135                (&size_str[..size_str.len()-1], 1024 * 1024 * 1024)
1136            } else {
1137                (size_str, 1)
1138            };
1139            
1140            if let Ok(number) = number_part.parse::<usize>() {
1141                return Some(number * multiplier);
1142            }
1143        }
1144    }
1145    None
1146}
1147
1148fn register_driver() {
1149    let fs_driver_manager = get_fs_driver_manager();
1150    fs_driver_manager.register_driver(Box::new(TmpFSDriver));
1151}
1152
1153driver_initcall!(register_driver);
1154
1155#[cfg(test)]
1156mod tests;