xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision 6d81180b3b7328466b976b69c5f7782aa66d8a89)
1ab5c8ca4Slogin use alloc::{boxed::Box, sync::Arc, vec::Vec};
2004e86ffSlogin 
3004e86ffSlogin use crate::{
4aa0367d6SLoGin     arch::asm::current::current_pcb,
52b771e32SGou Ngai     filesystem::vfs::file::FileDescriptorVec,
6aa0367d6SLoGin     include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM},
7004e86ffSlogin     io::SeekFrom,
82b771e32SGou Ngai     kerror,
9ab5c8ca4Slogin     syscall::{Syscall, SystemError},
10004e86ffSlogin };
11004e86ffSlogin 
12004e86ffSlogin use super::{
13ab5c8ca4Slogin     core::{do_mkdir, do_remove_dir, do_unlink_at},
14*6d81180bSLoGin     fcntl::{FcntlCommand, FD_CLOEXEC},
15004e86ffSlogin     file::{File, FileMode},
16ab5c8ca4Slogin     utils::rsplit_path,
17ab5c8ca4Slogin     Dirent, FileType, IndexNode, ROOT_INODE,
18004e86ffSlogin };
19004e86ffSlogin 
20ab5c8ca4Slogin pub const SEEK_SET: u32 = 0;
21ab5c8ca4Slogin pub const SEEK_CUR: u32 = 1;
22ab5c8ca4Slogin pub const SEEK_END: u32 = 2;
23ab5c8ca4Slogin pub const SEEK_MAX: u32 = 3;
24004e86ffSlogin 
25ab5c8ca4Slogin impl Syscall {
26ab5c8ca4Slogin     /// @brief 为当前进程打开一个文件
27ab5c8ca4Slogin     ///
28ab5c8ca4Slogin     /// @param path 文件路径
29ab5c8ca4Slogin     /// @param o_flags 打开文件的标志位
30ab5c8ca4Slogin     ///
31ab5c8ca4Slogin     /// @return 文件描述符编号,或者是错误码
32ab5c8ca4Slogin     pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
33*6d81180bSLoGin         // kdebug!("open: path: {}, mode: {:?}", path, mode);
34ab5c8ca4Slogin         // 文件名过长
35ab5c8ca4Slogin         if path.len() > PAGE_4K_SIZE as usize {
36ab5c8ca4Slogin             return Err(SystemError::ENAMETOOLONG);
37ab5c8ca4Slogin         }
38ab5c8ca4Slogin 
39ab5c8ca4Slogin         let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
40ab5c8ca4Slogin 
41ab5c8ca4Slogin         let inode: Arc<dyn IndexNode> = if inode.is_err() {
42ab5c8ca4Slogin             let errno = inode.unwrap_err();
43ab5c8ca4Slogin             // 文件不存在,且需要创建
44ab5c8ca4Slogin             if mode.contains(FileMode::O_CREAT)
45ab5c8ca4Slogin                 && !mode.contains(FileMode::O_DIRECTORY)
46ab5c8ca4Slogin                 && errno == SystemError::ENOENT
47ab5c8ca4Slogin             {
48ab5c8ca4Slogin                 let (filename, parent_path) = rsplit_path(path);
49ab5c8ca4Slogin                 // 查找父目录
50ab5c8ca4Slogin                 let parent_inode: Arc<dyn IndexNode> =
51ab5c8ca4Slogin                     ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
52ab5c8ca4Slogin                 // 创建文件
53ab5c8ca4Slogin                 let inode: Arc<dyn IndexNode> =
54ab5c8ca4Slogin                     parent_inode.create(filename, FileType::File, 0o777)?;
55ab5c8ca4Slogin                 inode
56004e86ffSlogin             } else {
57ab5c8ca4Slogin                 // 不需要创建文件,因此返回错误码
58ab5c8ca4Slogin                 return Err(errno);
59004e86ffSlogin             }
60004e86ffSlogin         } else {
61ab5c8ca4Slogin             inode.unwrap()
62004e86ffSlogin         };
63004e86ffSlogin 
64ab5c8ca4Slogin         let file_type: FileType = inode.metadata()?.file_type;
65ab5c8ca4Slogin         // 如果要打开的是文件夹,而目标不是文件夹
66ab5c8ca4Slogin         if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
67ab5c8ca4Slogin             return Err(SystemError::ENOTDIR);
68004e86ffSlogin         }
69ab5c8ca4Slogin 
70ab5c8ca4Slogin         // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
71ab5c8ca4Slogin         if mode.contains(FileMode::O_TRUNC)
72ab5c8ca4Slogin             && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY))
73ab5c8ca4Slogin             && file_type == FileType::File
74ab5c8ca4Slogin         {
75ab5c8ca4Slogin             inode.truncate(0)?;
76ab5c8ca4Slogin         }
77ab5c8ca4Slogin 
78ab5c8ca4Slogin         // 创建文件对象
79ab5c8ca4Slogin         let mut file: File = File::new(inode, mode)?;
80ab5c8ca4Slogin 
81ab5c8ca4Slogin         // 打开模式为“追加”
82ab5c8ca4Slogin         if mode.contains(FileMode::O_APPEND) {
83ab5c8ca4Slogin             file.lseek(SeekFrom::SeekEnd(0))?;
84ab5c8ca4Slogin         }
85ab5c8ca4Slogin 
86ab5c8ca4Slogin         // 把文件对象存入pcb
87*6d81180bSLoGin         let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize);
88*6d81180bSLoGin         // kdebug!("open: fd: {:?}", r);
89*6d81180bSLoGin         return r;
90ab5c8ca4Slogin     }
91ab5c8ca4Slogin 
92ab5c8ca4Slogin     /// @brief 关闭文件
93ab5c8ca4Slogin     ///
94ab5c8ca4Slogin     /// @param fd 文件描述符编号
95ab5c8ca4Slogin     ///
96ab5c8ca4Slogin     /// @return 成功返回0,失败返回错误码
97ab5c8ca4Slogin     pub fn close(fd: usize) -> Result<usize, SystemError> {
98*6d81180bSLoGin         // kdebug!("syscall::close: fd: {}", fd);
99ab5c8ca4Slogin         return current_pcb().drop_fd(fd as i32).map(|_| 0);
100ab5c8ca4Slogin     }
101ab5c8ca4Slogin 
102ab5c8ca4Slogin     /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
103ab5c8ca4Slogin     ///
104ab5c8ca4Slogin     /// @param fd 文件描述符编号
105ab5c8ca4Slogin     /// @param buf 输出缓冲区。
106ab5c8ca4Slogin     ///
107ab5c8ca4Slogin     /// @return Ok(usize) 成功读取的数据的字节数
108ab5c8ca4Slogin     /// @return Err(SystemError) 读取失败,返回posix错误码
109ab5c8ca4Slogin     pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
110*6d81180bSLoGin         // kdebug!("syscall::read: fd: {}, len={}", fd, buf.len());
111ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
112ab5c8ca4Slogin         if file.is_none() {
113ab5c8ca4Slogin             return Err(SystemError::EBADF);
114ab5c8ca4Slogin         }
115ab5c8ca4Slogin         let file: &mut File = file.unwrap();
116ab5c8ca4Slogin 
117ab5c8ca4Slogin         return file.read(buf.len(), buf);
118ab5c8ca4Slogin     }
119ab5c8ca4Slogin 
120ab5c8ca4Slogin     /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
121ab5c8ca4Slogin     ///
122ab5c8ca4Slogin     /// @param fd 文件描述符编号
123ab5c8ca4Slogin     /// @param buf 输入缓冲区。
124ab5c8ca4Slogin     ///
125ab5c8ca4Slogin     /// @return Ok(usize) 成功写入的数据的字节数
126ab5c8ca4Slogin     /// @return Err(SystemError) 写入失败,返回posix错误码
127ab5c8ca4Slogin     pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
128*6d81180bSLoGin         // kdebug!("syscall::write: fd: {}, len={}", fd, buf.len());
129ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
130ab5c8ca4Slogin         if file.is_none() {
131ab5c8ca4Slogin             return Err(SystemError::EBADF);
132ab5c8ca4Slogin         }
133ab5c8ca4Slogin         let file: &mut File = file.unwrap();
134ab5c8ca4Slogin 
135ab5c8ca4Slogin         return file.write(buf.len(), buf);
136ab5c8ca4Slogin     }
137ab5c8ca4Slogin 
138ab5c8ca4Slogin     /// @brief 调整文件操作指针的位置
139ab5c8ca4Slogin     ///
140ab5c8ca4Slogin     /// @param fd 文件描述符编号
141ab5c8ca4Slogin     /// @param seek 调整的方式
142ab5c8ca4Slogin     ///
143ab5c8ca4Slogin     /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
144ab5c8ca4Slogin     /// @return Err(SystemError) 调整失败,返回posix错误码
145ab5c8ca4Slogin     pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
146*6d81180bSLoGin         // kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek);
147ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
148ab5c8ca4Slogin         if file.is_none() {
149ab5c8ca4Slogin             return Err(SystemError::EBADF);
150ab5c8ca4Slogin         }
151ab5c8ca4Slogin         let file: &mut File = file.unwrap();
152ab5c8ca4Slogin         return file.lseek(seek);
153004e86ffSlogin     }
154004e86ffSlogin 
155004e86ffSlogin     /// @brief 切换工作目录
156004e86ffSlogin     ///
157004e86ffSlogin     /// @param dest_path 目标路径
158004e86ffSlogin     ///
159004e86ffSlogin     /// @return   返回码  描述
160004e86ffSlogin     ///      0       |          成功
161004e86ffSlogin     ///
162004e86ffSlogin     ///   EACCESS    |        权限不足
163004e86ffSlogin     ///
164004e86ffSlogin     ///    ELOOP     | 解析path时遇到路径循环
165004e86ffSlogin     ///
166004e86ffSlogin     /// ENAMETOOLONG |       路径名过长
167004e86ffSlogin     ///
168004e86ffSlogin     ///    ENOENT    |  目标文件或目录不存在
169004e86ffSlogin     ///
170004e86ffSlogin     ///    ENODIR    |  检索期间发现非目录项
171004e86ffSlogin     ///
172004e86ffSlogin     ///    ENOMEM    |      系统内存不足
173004e86ffSlogin     ///
174004e86ffSlogin     ///    EFAULT    |       错误的地址
175004e86ffSlogin     ///
176004e86ffSlogin     /// ENAMETOOLONG |        路径过长
177ab5c8ca4Slogin     pub fn chdir(dest_path: &str) -> Result<usize, SystemError> {
178ab5c8ca4Slogin         // Copy path to kernel space to avoid some security issues
179ab5c8ca4Slogin         let path: Box<&str> = Box::new(dest_path);
180004e86ffSlogin         let inode = match ROOT_INODE().lookup(&path) {
181004e86ffSlogin             Err(e) => {
182676b8ef6SMork                 kerror!("Change Directory Failed, Error = {:?}", e);
183ab5c8ca4Slogin                 return Err(SystemError::ENOENT);
184004e86ffSlogin             }
185004e86ffSlogin             Ok(i) => i,
186004e86ffSlogin         };
187004e86ffSlogin 
188004e86ffSlogin         match inode.metadata() {
189004e86ffSlogin             Err(e) => {
190676b8ef6SMork                 kerror!("INode Get MetaData Failed, Error = {:?}", e);
191ab5c8ca4Slogin                 return Err(SystemError::ENOENT);
192004e86ffSlogin             }
193004e86ffSlogin             Ok(i) => {
194004e86ffSlogin                 if let FileType::Dir = i.file_type {
195ab5c8ca4Slogin                     return Ok(0);
196004e86ffSlogin                 } else {
197ab5c8ca4Slogin                     return Err(SystemError::ENOTDIR);
198004e86ffSlogin                 }
199004e86ffSlogin             }
200004e86ffSlogin         }
201004e86ffSlogin     }
202004e86ffSlogin 
203004e86ffSlogin     /// @brief 获取目录中的数据
204004e86ffSlogin     ///
205ab5c8ca4Slogin     /// TODO: 这个函数的语义与Linux不一致,需要修改!!!
206ab5c8ca4Slogin     ///
207004e86ffSlogin     /// @param fd 文件描述符号
208ab5c8ca4Slogin     /// @param buf 输出缓冲区
209ab5c8ca4Slogin     ///
210ab5c8ca4Slogin     /// @return 成功返回读取的字节数,失败返回错误码
211ab5c8ca4Slogin     pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
212ab5c8ca4Slogin         let dirent =
213ab5c8ca4Slogin             unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?;
214004e86ffSlogin 
215004e86ffSlogin         if fd < 0 || fd as u32 > PROC_MAX_FD_NUM {
216ab5c8ca4Slogin             return Err(SystemError::EBADF);
217004e86ffSlogin         }
218004e86ffSlogin 
219004e86ffSlogin         // 获取fd
220004e86ffSlogin         let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) {
221004e86ffSlogin             None => {
222ab5c8ca4Slogin                 return Err(SystemError::EBADF);
223004e86ffSlogin             }
224004e86ffSlogin             Some(file) => file,
225004e86ffSlogin         };
226004e86ffSlogin         // kdebug!("file={file:?}");
227004e86ffSlogin 
228ab5c8ca4Slogin         return file.readdir(dirent).map(|x| x as usize);
229004e86ffSlogin     }
230004e86ffSlogin 
231004e86ffSlogin     /// @brief 创建文件夹
232004e86ffSlogin     ///
233004e86ffSlogin     /// @param path(r8) 路径 / mode(r9) 模式
234004e86ffSlogin     ///
235004e86ffSlogin     /// @return uint64_t 负数错误码 / 0表示成功
236ab5c8ca4Slogin     pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> {
237ab5c8ca4Slogin         return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
238004e86ffSlogin     }
239004e86ffSlogin 
240ab5c8ca4Slogin     /// **删除文件夹、取消文件的链接、删除文件的系统调用**
241004e86ffSlogin     ///
242ab5c8ca4Slogin     /// ## 参数
243004e86ffSlogin     ///
244ab5c8ca4Slogin     /// - `dirfd`:文件夹的文件描述符.目前暂未实现
245ab5c8ca4Slogin     /// - `pathname`:文件夹的路径
246ab5c8ca4Slogin     /// - `flags`:标志位
247004e86ffSlogin     ///
248004e86ffSlogin     ///
249ab5c8ca4Slogin     pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
250004e86ffSlogin         // kdebug!("sys_unlink_at={path:?}");
251ab5c8ca4Slogin         if (flags & (!AT_REMOVEDIR)) != 0 {
252ab5c8ca4Slogin             return Err(SystemError::EINVAL);
253004e86ffSlogin         }
254004e86ffSlogin 
255ab5c8ca4Slogin         if (flags & AT_REMOVEDIR) > 0 {
256004e86ffSlogin             // kdebug!("rmdir");
257ab5c8ca4Slogin             match do_remove_dir(&pathname) {
258004e86ffSlogin                 Err(err) => {
259676b8ef6SMork                     kerror!("Failed to Remove Directory, Error Code = {:?}", err);
260ab5c8ca4Slogin                     return Err(err);
261004e86ffSlogin                 }
262004e86ffSlogin                 Ok(_) => {
263ab5c8ca4Slogin                     return Ok(0);
264004e86ffSlogin                 }
265004e86ffSlogin             }
266004e86ffSlogin         }
267004e86ffSlogin 
268ab5c8ca4Slogin         match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) {
269004e86ffSlogin             Err(err) => {
270676b8ef6SMork                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
271ab5c8ca4Slogin                 return Err(err);
272004e86ffSlogin             }
273004e86ffSlogin             Ok(_) => {
274ab5c8ca4Slogin                 return Ok(0);
275004e86ffSlogin             }
276004e86ffSlogin         }
277004e86ffSlogin     }
2782b771e32SGou Ngai 
279ab5c8ca4Slogin     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
280ab5c8ca4Slogin     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
2812b771e32SGou Ngai         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
2822b771e32SGou Ngai             // 获得当前文件描述符数组
2832b771e32SGou Ngai             // 确认oldfd是否有效
2842b771e32SGou Ngai             if FileDescriptorVec::validate_fd(oldfd) {
2852b771e32SGou Ngai                 if let Some(file) = &fds.fds[oldfd as usize] {
2862b771e32SGou Ngai                     // 尝试获取对应的文件结构体
287ab5c8ca4Slogin                     let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?;
288ab5c8ca4Slogin 
2892b771e32SGou Ngai                     // 申请文件描述符,并把文件对象存入其中
290ab5c8ca4Slogin                     let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize);
2912b771e32SGou Ngai                     return res;
2922b771e32SGou Ngai                 }
2932b771e32SGou Ngai                 // oldfd对应的文件不存在
2942b771e32SGou Ngai                 return Err(SystemError::EBADF);
2952b771e32SGou Ngai             }
2962b771e32SGou Ngai             return Err(SystemError::EBADF);
2972b771e32SGou Ngai         } else {
2982b771e32SGou Ngai             return Err(SystemError::EMFILE);
2992b771e32SGou Ngai         }
3002b771e32SGou Ngai     }
3012b771e32SGou Ngai 
302ab5c8ca4Slogin     /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
303ab5c8ca4Slogin     /// 并返回新复制的文件结构体对应的fd.
304ab5c8ca4Slogin     /// 如果新fd已经打开,则会先关闭新fd.
305ab5c8ca4Slogin     ///
306ab5c8ca4Slogin     /// ## 参数
307ab5c8ca4Slogin     ///
308ab5c8ca4Slogin     /// - `oldfd`:旧文件描述符
309ab5c8ca4Slogin     /// - `newfd`:新文件描述符
310ab5c8ca4Slogin     ///
311ab5c8ca4Slogin     /// ## 返回值
312ab5c8ca4Slogin     ///
313ab5c8ca4Slogin     /// - 成功:新文件描述符
314ab5c8ca4Slogin     /// - 失败:错误码
315ab5c8ca4Slogin     pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> {
3162b771e32SGou Ngai         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
3172b771e32SGou Ngai             // 获得当前文件描述符数组
3182b771e32SGou Ngai             if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
3192b771e32SGou Ngai                 //确认oldfd, newid是否有效
3202b771e32SGou Ngai                 if oldfd == newfd {
3212b771e32SGou Ngai                     // 若oldfd与newfd相等
322ab5c8ca4Slogin                     return Ok(newfd as usize);
3232b771e32SGou Ngai                 }
3242b771e32SGou Ngai 
3252b771e32SGou Ngai                 if let Some(file) = &fds.fds[oldfd as usize] {
3262b771e32SGou Ngai                     if fds.fds[newfd as usize].is_some() {
3272b771e32SGou Ngai                         // close newfd
3282b771e32SGou Ngai                         if let Err(_) = current_pcb().drop_fd(newfd) {
3292b771e32SGou Ngai                             // An I/O error occurred while attempting to close fildes2.
3302b771e32SGou Ngai                             return Err(SystemError::EIO);
3312b771e32SGou Ngai                         }
3322b771e32SGou Ngai                     }
3332b771e32SGou Ngai 
3342b771e32SGou Ngai                     // 尝试获取对应的文件结构体
3352b771e32SGou Ngai                     let file_cp = file.try_clone();
3362b771e32SGou Ngai                     if file_cp.is_none() {
3372b771e32SGou Ngai                         return Err(SystemError::EBADF);
3382b771e32SGou Ngai                     }
3392b771e32SGou Ngai                     // 申请文件描述符,并把文件对象存入其中
340ab5c8ca4Slogin                     let res = current_pcb()
341ab5c8ca4Slogin                         .alloc_fd(*file_cp.unwrap(), Some(newfd))
342ab5c8ca4Slogin                         .map(|x| x as usize);
3432b771e32SGou Ngai 
3442b771e32SGou Ngai                     return res;
3452b771e32SGou Ngai                 }
3462b771e32SGou Ngai                 return Err(SystemError::EBADF);
3472b771e32SGou Ngai             } else {
3482b771e32SGou Ngai                 return Err(SystemError::EBADF);
3492b771e32SGou Ngai             }
3502b771e32SGou Ngai         }
3512b771e32SGou Ngai         // 从pcb获取文件描述符数组失败
3522b771e32SGou Ngai         return Err(SystemError::EMFILE);
3532b771e32SGou Ngai     }
354*6d81180bSLoGin 
355*6d81180bSLoGin     /// # fcntl
356*6d81180bSLoGin     ///
357*6d81180bSLoGin     /// ## 参数
358*6d81180bSLoGin     ///
359*6d81180bSLoGin     /// - `fd`:文件描述符
360*6d81180bSLoGin     /// - `cmd`:命令
361*6d81180bSLoGin     /// - `arg`:参数
362*6d81180bSLoGin     pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> {
363*6d81180bSLoGin         match cmd {
364*6d81180bSLoGin             FcntlCommand::DupFd => {
365*6d81180bSLoGin                 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
366*6d81180bSLoGin                     return Err(SystemError::EBADF);
367*6d81180bSLoGin                 }
368*6d81180bSLoGin                 let arg = arg as usize;
369*6d81180bSLoGin                 for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
370*6d81180bSLoGin                     if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
371*6d81180bSLoGin                         if fds.fds[i as usize].is_none() {
372*6d81180bSLoGin                             return Self::dup2(fd, i as i32);
373*6d81180bSLoGin                         }
374*6d81180bSLoGin                     }
375*6d81180bSLoGin                 }
376*6d81180bSLoGin                 return Err(SystemError::EMFILE);
377*6d81180bSLoGin             }
378*6d81180bSLoGin             FcntlCommand::GetFd => {
379*6d81180bSLoGin                 // Get file descriptor flags.
380*6d81180bSLoGin 
381*6d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
382*6d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
383*6d81180bSLoGin                         if let Some(file) = &fds.fds[fd as usize] {
384*6d81180bSLoGin                             if file.close_on_exec() {
385*6d81180bSLoGin                                 return Ok(FD_CLOEXEC as usize);
386*6d81180bSLoGin                             }
387*6d81180bSLoGin                         }
388*6d81180bSLoGin                         return Err(SystemError::EBADF);
389*6d81180bSLoGin                     }
390*6d81180bSLoGin                 }
391*6d81180bSLoGin                 return Err(SystemError::EBADF);
392*6d81180bSLoGin             }
393*6d81180bSLoGin             FcntlCommand::SetFd => {
394*6d81180bSLoGin                 // Set file descriptor flags.
395*6d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
396*6d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
397*6d81180bSLoGin                         if let Some(file) = &mut fds.fds[fd as usize] {
398*6d81180bSLoGin                             let arg = arg as u32;
399*6d81180bSLoGin                             if arg & FD_CLOEXEC != 0 {
400*6d81180bSLoGin                                 file.set_close_on_exec(true);
401*6d81180bSLoGin                             } else {
402*6d81180bSLoGin                                 file.set_close_on_exec(false);
403*6d81180bSLoGin                             }
404*6d81180bSLoGin                             return Ok(0);
405*6d81180bSLoGin                         }
406*6d81180bSLoGin                         return Err(SystemError::EBADF);
407*6d81180bSLoGin                     }
408*6d81180bSLoGin                 }
409*6d81180bSLoGin                 return Err(SystemError::EBADF);
410*6d81180bSLoGin             }
411*6d81180bSLoGin 
412*6d81180bSLoGin             FcntlCommand::GetFlags => {
413*6d81180bSLoGin                 // Get file status flags.
414*6d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
415*6d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
416*6d81180bSLoGin                         if let Some(file) = &fds.fds[fd as usize] {
417*6d81180bSLoGin                             return Ok(file.mode().bits() as usize);
418*6d81180bSLoGin                         }
419*6d81180bSLoGin                         return Err(SystemError::EBADF);
420*6d81180bSLoGin                     }
421*6d81180bSLoGin                 }
422*6d81180bSLoGin                 return Err(SystemError::EBADF);
423*6d81180bSLoGin             }
424*6d81180bSLoGin             FcntlCommand::SetFlags => {
425*6d81180bSLoGin                 // Set file status flags.
426*6d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
427*6d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
428*6d81180bSLoGin                         if let Some(file) = &mut fds.fds[fd as usize] {
429*6d81180bSLoGin                             let arg = arg as u32;
430*6d81180bSLoGin                             let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?;
431*6d81180bSLoGin                             file.set_mode(mode)?;
432*6d81180bSLoGin                             return Ok(0);
433*6d81180bSLoGin                         }
434*6d81180bSLoGin                         return Err(SystemError::EBADF);
435*6d81180bSLoGin                     }
436*6d81180bSLoGin                 }
437*6d81180bSLoGin                 return Err(SystemError::EBADF);
438*6d81180bSLoGin             }
439*6d81180bSLoGin             _ => {
440*6d81180bSLoGin                 // TODO: unimplemented
441*6d81180bSLoGin                 // 未实现的命令,返回0,不报错。
442*6d81180bSLoGin 
443*6d81180bSLoGin                 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
444*6d81180bSLoGin                 return Ok(0);
445*6d81180bSLoGin             }
446*6d81180bSLoGin         }
447*6d81180bSLoGin     }
448*6d81180bSLoGin 
449*6d81180bSLoGin     /// # ftruncate
450*6d81180bSLoGin     ///
451*6d81180bSLoGin     /// ## 描述
452*6d81180bSLoGin     ///
453*6d81180bSLoGin     /// 改变文件大小.
454*6d81180bSLoGin     /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充.
455*6d81180bSLoGin     /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小.
456*6d81180bSLoGin     ///
457*6d81180bSLoGin     /// ## 参数
458*6d81180bSLoGin     ///
459*6d81180bSLoGin     /// - `fd`:文件描述符
460*6d81180bSLoGin     /// - `len`:文件大小
461*6d81180bSLoGin     ///
462*6d81180bSLoGin     /// ## 返回值
463*6d81180bSLoGin     ///
464*6d81180bSLoGin     /// 如果成功,返回0,否则返回错误码.
465*6d81180bSLoGin     pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> {
466*6d81180bSLoGin         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
467*6d81180bSLoGin             if FileDescriptorVec::validate_fd(fd) {
468*6d81180bSLoGin                 if let Some(file) = &mut fds.fds[fd as usize] {
469*6d81180bSLoGin                     let r = file.ftruncate(len).map(|_| 0);
470*6d81180bSLoGin                     return r;
471*6d81180bSLoGin                 }
472*6d81180bSLoGin                 return Err(SystemError::EBADF);
473*6d81180bSLoGin             }
474*6d81180bSLoGin         }
475*6d81180bSLoGin         return Err(SystemError::EBADF);
476*6d81180bSLoGin     }
4772b771e32SGou Ngai }
478cde5492fSlogin 
479cde5492fSlogin #[repr(C)]
480cde5492fSlogin #[derive(Debug, Clone, Copy)]
481cde5492fSlogin pub struct IoVec {
482cde5492fSlogin     /// 缓冲区的起始地址
483cde5492fSlogin     pub iov_base: *mut u8,
484cde5492fSlogin     /// 缓冲区的长度
485cde5492fSlogin     pub iov_len: usize,
486cde5492fSlogin }
487cde5492fSlogin 
488cde5492fSlogin /// 用于存储多个来自用户空间的IoVec
489cde5492fSlogin ///
490cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
491cde5492fSlogin /// TODO:支持分散读写
492cde5492fSlogin #[derive(Debug)]
493cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>);
494cde5492fSlogin 
495cde5492fSlogin impl IoVecs {
496cde5492fSlogin     /// 从用户空间的IoVec中构造IoVecs
497cde5492fSlogin     ///
498cde5492fSlogin     /// @param iov 用户空间的IoVec
499cde5492fSlogin     /// @param iovcnt 用户空间的IoVec的数量
500cde5492fSlogin     /// @param readv 是否为readv系统调用
501cde5492fSlogin     ///
502cde5492fSlogin     /// @return 构造成功返回IoVecs,否则返回错误码
503cde5492fSlogin     pub unsafe fn from_user(
504cde5492fSlogin         iov: *const IoVec,
505cde5492fSlogin         iovcnt: usize,
506cde5492fSlogin         _readv: bool,
507cde5492fSlogin     ) -> Result<Self, SystemError> {
508cde5492fSlogin         // 检查iov指针所在空间是否合法
509cde5492fSlogin         if !verify_area(
510cde5492fSlogin             iov as usize as u64,
511cde5492fSlogin             (iovcnt * core::mem::size_of::<IoVec>()) as u64,
512cde5492fSlogin         ) {
513cde5492fSlogin             return Err(SystemError::EFAULT);
514cde5492fSlogin         }
515cde5492fSlogin 
516cde5492fSlogin         // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
517cde5492fSlogin         let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
518cde5492fSlogin 
519cde5492fSlogin         let mut slices: Vec<&mut [u8]> = vec![];
520cde5492fSlogin         slices.reserve(iovs.len());
521cde5492fSlogin 
522cde5492fSlogin         for iov in iovs.iter() {
523cde5492fSlogin             if iov.iov_len == 0 {
524cde5492fSlogin                 continue;
525cde5492fSlogin             }
526cde5492fSlogin 
527cde5492fSlogin             if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) {
528cde5492fSlogin                 return Err(SystemError::EFAULT);
529cde5492fSlogin             }
530cde5492fSlogin 
531cde5492fSlogin             slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
532cde5492fSlogin         }
533cde5492fSlogin 
534cde5492fSlogin         return Ok(Self(slices));
535cde5492fSlogin     }
536cde5492fSlogin 
537cde5492fSlogin     /// @brief 将IoVecs中的数据聚合到一个缓冲区中
538cde5492fSlogin     ///
539cde5492fSlogin     /// @return 返回聚合后的缓冲区
540cde5492fSlogin     pub fn gather(&self) -> Vec<u8> {
541cde5492fSlogin         let mut buf = Vec::new();
542cde5492fSlogin         for slice in self.0.iter() {
543cde5492fSlogin             buf.extend_from_slice(slice);
544cde5492fSlogin         }
545cde5492fSlogin         return buf;
546cde5492fSlogin     }
547cde5492fSlogin 
548cde5492fSlogin     /// @brief 将给定的数据分散写入到IoVecs中
549cde5492fSlogin     pub fn scatter(&mut self, data: &[u8]) {
550cde5492fSlogin         let mut data: &[u8] = data;
551cde5492fSlogin         for slice in self.0.iter_mut() {
552cde5492fSlogin             let len = core::cmp::min(slice.len(), data.len());
553cde5492fSlogin             if len == 0 {
554cde5492fSlogin                 continue;
555cde5492fSlogin             }
556cde5492fSlogin 
557cde5492fSlogin             slice[..len].copy_from_slice(&data[..len]);
558cde5492fSlogin             data = &data[len..];
559cde5492fSlogin         }
560cde5492fSlogin     }
561cde5492fSlogin 
562cde5492fSlogin     /// @brief 创建与IoVecs等长的缓冲区
563cde5492fSlogin     ///
564cde5492fSlogin     /// @param set_len 是否设置返回的Vec的len。
565cde5492fSlogin     /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
566cde5492fSlogin     /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
567cde5492fSlogin     ///
568cde5492fSlogin     /// @return 返回创建的缓冲区
569cde5492fSlogin     pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
570cde5492fSlogin         let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
571cde5492fSlogin         let mut buf: Vec<u8> = Vec::with_capacity(total_len);
572cde5492fSlogin 
573cde5492fSlogin         if set_len {
574cde5492fSlogin             unsafe {
575cde5492fSlogin                 buf.set_len(total_len);
576cde5492fSlogin             }
577cde5492fSlogin         }
578cde5492fSlogin         return buf;
579cde5492fSlogin     }
580cde5492fSlogin }
581