Skip to main content

tg_easy_fs/
file.rs

1use core::cell::Cell;
2
3use crate::Inode;
4use alloc::string::String;
5use alloc::sync::Arc;
6use alloc::vec::Vec;
7use bitflags::*;
8
9// 教程阅读建议:
10// - 先看 `UserBuffer`:理解“跨页用户缓冲区”在内核中的统一抽象;
11// - 再看 `FileHandle`:理解 inode + offset + 读写权限如何组成最小文件描述符语义。
12
13/// Array of u8 slice that user communicate with os
14pub struct UserBuffer {
15    /// U8 vec
16    pub buffers: Vec<&'static mut [u8]>,
17}
18
19impl UserBuffer {
20    /// Create a `UserBuffer` by parameter
21    pub fn new(buffers: Vec<&'static mut [u8]>) -> Self {
22        Self { buffers }
23    }
24    /// 获取 `UserBuffer` 的总长度。
25    pub fn len(&self) -> usize {
26        let mut total: usize = 0;
27        for b in self.buffers.iter() {
28            total += b.len();
29        }
30        total
31    }
32
33    /// 检查 `UserBuffer` 是否为空。
34    pub fn is_empty(&self) -> bool {
35        self.buffers.is_empty()
36    }
37}
38
39impl IntoIterator for UserBuffer {
40    type Item = *mut u8;
41    type IntoIter = UserBufferIterator;
42    fn into_iter(self) -> Self::IntoIter {
43        // 将“分段缓冲区”拍平为字节指针迭代器,便于 pipe/file 统一按字节处理。
44        UserBufferIterator {
45            buffers: self.buffers,
46            current_buffer: 0,
47            current_idx: 0,
48        }
49    }
50}
51
52/// 用户缓冲区迭代器
53pub struct UserBufferIterator {
54    buffers: Vec<&'static mut [u8]>,
55    current_buffer: usize,
56    current_idx: usize,
57}
58
59impl Iterator for UserBufferIterator {
60    type Item = *mut u8;
61    fn next(&mut self) -> Option<Self::Item> {
62        if self.current_buffer >= self.buffers.len() {
63            None
64        } else {
65            // 依次遍历每个分片,读完当前分片后自动切到下一个分片。
66            let r = &mut self.buffers[self.current_buffer][self.current_idx] as *mut _;
67            if self.current_idx + 1 == self.buffers[self.current_buffer].len() {
68                self.current_idx = 0;
69                self.current_buffer += 1;
70            } else {
71                self.current_idx += 1;
72            }
73            Some(r)
74        }
75    }
76}
77
78bitflags! {
79  /// Open file flags
80  pub struct OpenFlags: u32 {
81      /// Read only
82      const RDONLY = 0;
83      /// Write only
84      const WRONLY = 1 << 0;
85      /// Read & Write
86      const RDWR = 1 << 1;
87      /// Allow create
88      const CREATE = 1 << 9;
89      /// Clear file and return an empty one
90      const TRUNC = 1 << 10;
91  }
92}
93
94impl OpenFlags {
95    /// Do not check validity for simplicity
96    /// Return (readable, writable)
97    pub fn read_write(&self) -> (bool, bool) {
98        // 与课程内核约定保持一致:RDONLY(0) -> 只读;WRONLY -> 只写;其他组合按读写处理。
99        if self.is_empty() {
100            (true, false)
101        } else if self.contains(Self::WRONLY) {
102            (false, true)
103        } else {
104            (true, true)
105        }
106    }
107}
108
109/// Cached file metadata in memory
110#[derive(Clone)]
111pub struct FileHandle {
112    /// FileSystem Inode
113    pub inode: Option<Arc<Inode>>,
114    /// Open options: able to read
115    pub read: bool,
116    /// Open options: able to write
117    pub write: bool,
118    /// Current offset
119    pub offset: Cell<usize>,
120}
121
122impl FileHandle {
123    /// 创建一个新的文件句柄。
124    pub fn new(read: bool, write: bool, inode: Arc<Inode>) -> Self {
125        Self {
126            inode: Some(inode),
127            read,
128            write,
129            offset: Cell::new(0),
130        }
131    }
132
133    /// 创建一个空的文件句柄(无 inode)。
134    pub fn empty(read: bool, write: bool) -> Self {
135        Self {
136            inode: None,
137            read,
138            write,
139            offset: Cell::new(0),
140        }
141    }
142
143    /// 是否可读。
144    pub fn readable(&self) -> bool {
145        self.read
146    }
147
148    /// 是否可写。
149    pub fn writable(&self) -> bool {
150        self.write
151    }
152
153    /// 从文件读取数据到用户缓冲区。
154    pub fn read(&self, mut buf: UserBuffer) -> isize {
155        let mut total_read_size: usize = 0;
156        if let Some(inode) = &self.inode {
157            // 按分片循环读取,并维护文件偏移 offset。
158            for slice in buf.buffers.iter_mut() {
159                let read_size = inode.read_at(self.offset.get(), slice);
160                if read_size == 0 {
161                    break;
162                }
163                self.offset.set(self.offset.get() + read_size);
164                total_read_size += read_size;
165            }
166            total_read_size as _
167        } else {
168            -1
169        }
170    }
171
172    /// 将用户缓冲区数据写入文件。
173    pub fn write(&self, buf: UserBuffer) -> isize {
174        let mut total_write_size: usize = 0;
175        if let Some(inode) = &self.inode {
176            // 连续写入每个分片,偏移随写入量前移。
177            for slice in buf.buffers.iter() {
178                let write_size = inode.write_at(self.offset.get(), slice);
179                assert_eq!(write_size, slice.len());
180                self.offset.set(self.offset.get() + write_size);
181                total_write_size += write_size;
182            }
183            total_write_size as _
184        } else {
185            -1
186        }
187    }
188}
189
190/// 文件系统管理器 trait。
191pub trait FSManager {
192    /// 打开文件。
193    fn open(&self, path: &str, flags: OpenFlags) -> Option<Arc<FileHandle>>;
194
195    /// 查找文件。
196    fn find(&self, path: &str) -> Option<Arc<Inode>>;
197
198    /// 创建硬链接。
199    fn link(&self, src: &str, dst: &str) -> isize;
200
201    /// 删除硬链接。
202    fn unlink(&self, path: &str) -> isize;
203
204    /// 列出目录内容。
205    fn readdir(&self, path: &str) -> Option<Vec<String>>;
206}