xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision cde5492f725681ed89abe1e6eb088e05d943d793)
1004e86ffSlogin use core::ffi::{c_char, CStr};
2004e86ffSlogin 
3*cde5492fSlogin use alloc::{boxed::Box, string::ToString, vec::Vec};
4004e86ffSlogin 
5004e86ffSlogin use crate::{
6004e86ffSlogin     arch::asm::{current::current_pcb, ptrace::user_mode},
72b771e32SGou Ngai     filesystem::vfs::file::FileDescriptorVec,
8004e86ffSlogin     include::bindings::bindings::{
92b771e32SGou Ngai         pt_regs, verify_area, AT_REMOVEDIR, PAGE_2M_SIZE, PAGE_4K_SIZE, PROC_MAX_FD_NUM, SEEK_CUR,
102b771e32SGou Ngai         SEEK_END, SEEK_MAX, SEEK_SET,
11004e86ffSlogin     },
12004e86ffSlogin     io::SeekFrom,
132b771e32SGou Ngai     kerror,
142b771e32SGou Ngai     syscall::SystemError,
15004e86ffSlogin };
16004e86ffSlogin 
17004e86ffSlogin use super::{
18004e86ffSlogin     core::{do_lseek, do_mkdir, do_open, do_read, do_remove_dir, do_unlink_at, do_write},
19004e86ffSlogin     file::{File, FileMode},
20004e86ffSlogin     Dirent, FileType, ROOT_INODE,
21004e86ffSlogin };
22004e86ffSlogin 
23004e86ffSlogin /// @brief 打开文件
24004e86ffSlogin ///
25004e86ffSlogin /// @param regs->r8 path 文件路径
26004e86ffSlogin /// @param regs->r9 o_flags 打开文件的标志位
27004e86ffSlogin ///
28004e86ffSlogin /// @return u64 文件描述符编号,或者是错误码
29004e86ffSlogin #[no_mangle]
30004e86ffSlogin pub extern "C" fn sys_open(regs: &pt_regs) -> u64 {
31004e86ffSlogin     let path: &CStr = unsafe { CStr::from_ptr(regs.r8 as usize as *const c_char) };
32004e86ffSlogin     let path: Result<&str, core::str::Utf8Error> = path.to_str();
33004e86ffSlogin     if path.is_err() {
34676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
35004e86ffSlogin     }
36004e86ffSlogin     let path: &str = path.unwrap();
37004e86ffSlogin     let flags = regs.r9;
38004e86ffSlogin     let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32);
39676b8ef6SMork     let r: Result<i32, SystemError> = do_open(path, open_flags);
40004e86ffSlogin 
41004e86ffSlogin     if r.is_ok() {
42004e86ffSlogin         return r.unwrap() as u64;
43004e86ffSlogin     } else {
44676b8ef6SMork         return r.unwrap_err().to_posix_errno() as u64;
45004e86ffSlogin     }
46004e86ffSlogin }
47004e86ffSlogin 
48004e86ffSlogin /// @brief 关闭文件的系统调用函数
49004e86ffSlogin ///
50004e86ffSlogin /// @param regs->r8 fd:文件描述符编号
51004e86ffSlogin #[no_mangle]
52004e86ffSlogin pub extern "C" fn sys_close(regs: &pt_regs) -> u64 {
53004e86ffSlogin     let fd = regs.r8 as i32;
54676b8ef6SMork     let r: Result<(), SystemError> = current_pcb().drop_fd(fd);
55004e86ffSlogin 
56004e86ffSlogin     if r.is_ok() {
57004e86ffSlogin         return 0;
58004e86ffSlogin     } else {
59676b8ef6SMork         return r.unwrap_err().to_posix_errno() as u64;
60004e86ffSlogin     }
61004e86ffSlogin }
62004e86ffSlogin 
63004e86ffSlogin /// @brief 读取文件的系统调用函数
64004e86ffSlogin ///
65004e86ffSlogin /// @param regs->r8 文件描述符编号
66004e86ffSlogin /// @param regs->r9 输出缓冲区
67004e86ffSlogin /// @param regs->r10 要读取的长度
68004e86ffSlogin #[no_mangle]
69004e86ffSlogin pub extern "C" fn sys_read(regs: &pt_regs) -> u64 {
70004e86ffSlogin     let fd = regs.r8 as i32;
71004e86ffSlogin     let buf_vaddr = regs.r9 as usize;
72004e86ffSlogin     let len = regs.r10 as usize;
73004e86ffSlogin 
74004e86ffSlogin     // 判断缓冲区是否来自用户态,进行权限校验
75004e86ffSlogin     if user_mode(regs) && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
76004e86ffSlogin         // 来自用户态,而buffer在内核态,这样的操作不被允许
77676b8ef6SMork         return SystemError::EPERM.to_posix_errno() as u64;
78004e86ffSlogin     }
79004e86ffSlogin 
80004e86ffSlogin     let buf: &mut [u8] =
81004e86ffSlogin         unsafe { core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len) };
82004e86ffSlogin 
83676b8ef6SMork     let r: Result<usize, SystemError> = do_read(fd, buf);
84004e86ffSlogin 
85004e86ffSlogin     if r.is_ok() {
86004e86ffSlogin         return r.unwrap() as u64;
87004e86ffSlogin     } else {
88676b8ef6SMork         return r.unwrap_err().to_posix_errno() as u64;
89004e86ffSlogin     }
90004e86ffSlogin }
91004e86ffSlogin 
92004e86ffSlogin /// @brief 向文件写入数据的系统调用函数
93004e86ffSlogin ///
94004e86ffSlogin /// @param regs->r8 文件描述符编号
95004e86ffSlogin /// @param regs->r9 输入缓冲区
96004e86ffSlogin /// @param regs->r10 要写入的长度
97004e86ffSlogin #[no_mangle]
98004e86ffSlogin pub extern "C" fn sys_write(regs: &pt_regs) -> u64 {
99004e86ffSlogin     let fd = regs.r8 as i32;
100004e86ffSlogin     let buf_vaddr = regs.r9 as usize;
101004e86ffSlogin     let len = regs.r10 as usize;
102004e86ffSlogin 
103004e86ffSlogin     // 判断缓冲区是否来自用户态,进行权限校验
104004e86ffSlogin     if user_mode(regs) && unsafe { !verify_area(buf_vaddr as u64, len as u64) } {
105004e86ffSlogin         // 来自用户态,而buffer在内核态,这样的操作不被允许
106676b8ef6SMork         return SystemError::EPERM.to_posix_errno() as u64;
107004e86ffSlogin     }
108004e86ffSlogin 
109004e86ffSlogin     let buf: &[u8] =
110004e86ffSlogin         unsafe { core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *mut u8, len) };
111004e86ffSlogin 
112676b8ef6SMork     let r: Result<usize, SystemError> = do_write(fd, buf);
113004e86ffSlogin 
114004e86ffSlogin     if r.is_ok() {
115004e86ffSlogin         return r.unwrap() as u64;
116004e86ffSlogin     } else {
117676b8ef6SMork         return r.unwrap_err().to_posix_errno() as u64;
118004e86ffSlogin     }
119004e86ffSlogin }
120004e86ffSlogin 
121004e86ffSlogin /// @brief 调整文件访问指针位置的系统调用函数
122004e86ffSlogin ///
123004e86ffSlogin /// @param regs->r8 文件描述符编号
124004e86ffSlogin /// @param regs->r9 调整偏移量
125004e86ffSlogin /// @param regs->r10 调整的模式
126004e86ffSlogin #[no_mangle]
127004e86ffSlogin pub extern "C" fn sys_lseek(regs: &pt_regs) -> u64 {
128004e86ffSlogin     let fd = regs.r8 as i32;
129004e86ffSlogin     let offset = regs.r9 as i64;
130004e86ffSlogin     let whence = regs.r10 as u32;
131004e86ffSlogin 
132004e86ffSlogin     let w: SeekFrom = match whence {
133004e86ffSlogin         SEEK_SET => SeekFrom::SeekSet(offset),
134004e86ffSlogin         SEEK_CUR => SeekFrom::SeekCurrent(offset),
135004e86ffSlogin         SEEK_END => SeekFrom::SeekEnd(offset),
136004e86ffSlogin         SEEK_MAX => SeekFrom::SeekEnd(0),
137676b8ef6SMork         _ => return SystemError::EINVAL.to_posix_errno() as u64,
138004e86ffSlogin     };
139004e86ffSlogin 
140676b8ef6SMork     let r: Result<usize, SystemError> = do_lseek(fd, w);
141004e86ffSlogin     if r.is_ok() {
142004e86ffSlogin         return r.unwrap() as u64;
143004e86ffSlogin     } else {
144676b8ef6SMork         return r.unwrap_err().to_posix_errno() as u64;
145004e86ffSlogin     }
146004e86ffSlogin }
147004e86ffSlogin 
148004e86ffSlogin /// @brief 切换工作目录
149004e86ffSlogin ///
150004e86ffSlogin /// @param dest_path 目标路径
151004e86ffSlogin ///
152004e86ffSlogin /// @return   返回码  描述
153004e86ffSlogin ///      0       |          成功
154004e86ffSlogin ///
155004e86ffSlogin ///   EACCESS    |        权限不足
156004e86ffSlogin ///
157004e86ffSlogin ///    ELOOP     | 解析path时遇到路径循环
158004e86ffSlogin ///
159004e86ffSlogin /// ENAMETOOLONG |       路径名过长
160004e86ffSlogin ///
161004e86ffSlogin ///    ENOENT    |  目标文件或目录不存在
162004e86ffSlogin ///
163004e86ffSlogin ///    ENODIR    |  检索期间发现非目录项
164004e86ffSlogin ///
165004e86ffSlogin ///    ENOMEM    |      系统内存不足
166004e86ffSlogin ///
167004e86ffSlogin ///    EFAULT    |       错误的地址
168004e86ffSlogin ///
169004e86ffSlogin /// ENAMETOOLONG |        路径过长
170004e86ffSlogin #[no_mangle]
171004e86ffSlogin pub extern "C" fn sys_chdir(regs: &pt_regs) -> u64 {
172004e86ffSlogin     if regs.r8 == 0 {
173676b8ef6SMork         return SystemError::EFAULT.to_posix_errno() as u64;
174004e86ffSlogin     }
175004e86ffSlogin     let ptr = regs.r8 as usize as *const c_char;
176004e86ffSlogin     // 权限校验
177004e86ffSlogin     if ptr.is_null()
178004e86ffSlogin         || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) })
179004e86ffSlogin     {
180676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
181004e86ffSlogin     }
182004e86ffSlogin 
183004e86ffSlogin     let dest_path: &CStr = unsafe { CStr::from_ptr(ptr) };
184004e86ffSlogin     let dest_path: Result<&str, core::str::Utf8Error> = dest_path.to_str();
185004e86ffSlogin 
186004e86ffSlogin     if dest_path.is_err() {
187676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
188004e86ffSlogin     }
189004e86ffSlogin 
190004e86ffSlogin     let dest_path: &str = dest_path.unwrap();
191004e86ffSlogin 
192004e86ffSlogin     if dest_path.len() == 0 {
193676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
194004e86ffSlogin     } else if dest_path.len() >= PAGE_4K_SIZE as usize {
195676b8ef6SMork         return SystemError::ENAMETOOLONG.to_posix_errno() as u64;
196004e86ffSlogin     }
197004e86ffSlogin 
198004e86ffSlogin     let path = Box::new(dest_path.clone());
199004e86ffSlogin     let inode = match ROOT_INODE().lookup(&path) {
200004e86ffSlogin         Err(e) => {
201676b8ef6SMork             kerror!("Change Directory Failed, Error = {:?}", e);
202676b8ef6SMork             return SystemError::ENOENT.to_posix_errno() as u64;
203004e86ffSlogin         }
204004e86ffSlogin         Ok(i) => i,
205004e86ffSlogin     };
206004e86ffSlogin 
207004e86ffSlogin     match inode.metadata() {
208004e86ffSlogin         Err(e) => {
209676b8ef6SMork             kerror!("INode Get MetaData Failed, Error = {:?}", e);
210676b8ef6SMork             return SystemError::ENOENT.to_posix_errno() as u64;
211004e86ffSlogin         }
212004e86ffSlogin         Ok(i) => {
213004e86ffSlogin             if let FileType::Dir = i.file_type {
214004e86ffSlogin                 return 0;
215004e86ffSlogin             } else {
216676b8ef6SMork                 return SystemError::ENOTDIR.to_posix_errno() as u64;
217004e86ffSlogin             }
218004e86ffSlogin         }
219004e86ffSlogin     }
220004e86ffSlogin }
221004e86ffSlogin 
222004e86ffSlogin /// @brief 获取目录中的数据
223004e86ffSlogin ///
224004e86ffSlogin /// @param fd 文件描述符号
225004e86ffSlogin /// @return uint64_t dirent的总大小
226004e86ffSlogin #[no_mangle]
227004e86ffSlogin pub extern "C" fn sys_getdents(regs: &pt_regs) -> u64 {
228004e86ffSlogin     let fd = regs.r8 as i32;
229004e86ffSlogin     let count = regs.r10 as i64;
230004e86ffSlogin     let dirent = match unsafe { (regs.r9 as usize as *mut Dirent).as_mut() } {
231004e86ffSlogin         None => {
232004e86ffSlogin             return 0;
233004e86ffSlogin         }
234004e86ffSlogin         Some(dirent) => dirent,
235004e86ffSlogin     };
236004e86ffSlogin 
237004e86ffSlogin     if fd < 0 || fd as u32 > PROC_MAX_FD_NUM {
238676b8ef6SMork         return SystemError::EBADF.to_posix_errno() as u64;
239004e86ffSlogin     }
240004e86ffSlogin 
241004e86ffSlogin     if count < 0 {
242676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
243004e86ffSlogin     }
244004e86ffSlogin 
245004e86ffSlogin     // 获取fd
246004e86ffSlogin     let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) {
247004e86ffSlogin         None => {
248676b8ef6SMork             return SystemError::EBADF.to_posix_errno() as u64;
249004e86ffSlogin         }
250004e86ffSlogin         Some(file) => file,
251004e86ffSlogin     };
252004e86ffSlogin     // kdebug!("file={file:?}");
253004e86ffSlogin 
254004e86ffSlogin     return match file.readdir(dirent) {
255004e86ffSlogin         Err(_) => 0,
256004e86ffSlogin         Ok(len) => len,
257004e86ffSlogin     };
258004e86ffSlogin }
259004e86ffSlogin 
260004e86ffSlogin /// @brief 创建文件夹
261004e86ffSlogin ///
262004e86ffSlogin /// @param path(r8) 路径 / mode(r9) 模式
263004e86ffSlogin ///
264004e86ffSlogin /// @return uint64_t 负数错误码 / 0表示成功
265004e86ffSlogin #[no_mangle]
266004e86ffSlogin pub extern "C" fn sys_mkdir(regs: &pt_regs) -> u64 {
267004e86ffSlogin     let ptr = regs.r8 as usize as *const c_char;
268004e86ffSlogin     if ptr.is_null()
269004e86ffSlogin         || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) })
270004e86ffSlogin     {
271676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
272004e86ffSlogin     }
273004e86ffSlogin     let path: &CStr = unsafe { CStr::from_ptr(ptr) };
274004e86ffSlogin     let path: Result<&str, core::str::Utf8Error> = path.to_str();
275004e86ffSlogin     let mode = regs.r9;
276004e86ffSlogin 
277004e86ffSlogin     if path.is_err() {
278676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
279004e86ffSlogin     }
280004e86ffSlogin 
281004e86ffSlogin     let path = &path.unwrap().to_string();
282004e86ffSlogin     if path.trim() == "" {
283676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
284004e86ffSlogin     }
285004e86ffSlogin 
28684407d36Slogin     return match do_mkdir(&path.trim(), FileMode::from_bits_truncate(mode as u32)) {
287004e86ffSlogin         Err(err) => {
288676b8ef6SMork             kerror!("Failed in do_mkdir, Error Code = {:#?}", err);
289676b8ef6SMork             err.to_posix_errno() as u64
290004e86ffSlogin         }
291004e86ffSlogin         Ok(_) => 0,
292004e86ffSlogin     };
293004e86ffSlogin }
294004e86ffSlogin 
295004e86ffSlogin ///@brief 删除文件夹、取消文件的链接、删除文件的系统调用
296004e86ffSlogin ///
297004e86ffSlogin ///@param regs->r8 dfd 进程相对路径基准目录的文件描述符(见fcntl.h)
298004e86ffSlogin ///
299004e86ffSlogin ///@param regs->r9 路径名称字符串
300004e86ffSlogin ///
301004e86ffSlogin ///@param regs->r10 flag 预留的标志位,暂时未使用,请置为0。
302004e86ffSlogin ///
303004e86ffSlogin ///@return uint64_t 错误码
304004e86ffSlogin #[no_mangle]
305004e86ffSlogin pub extern "C" fn sys_unlink_at(regs: &pt_regs) -> u64 {
306004e86ffSlogin     let _dfd = regs.r8;
307004e86ffSlogin     let ptr = regs.r9 as usize as *const c_char;
308004e86ffSlogin     if ptr.is_null()
309004e86ffSlogin         || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) })
310004e86ffSlogin     {
311676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
312004e86ffSlogin     }
313004e86ffSlogin     let path: &CStr = unsafe { CStr::from_ptr(ptr) };
314004e86ffSlogin     let path: Result<&str, core::str::Utf8Error> = path.to_str();
315004e86ffSlogin     let flag = regs.r10;
316004e86ffSlogin     if path.is_err() {
317676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
318004e86ffSlogin     }
319004e86ffSlogin 
320004e86ffSlogin     let path = &path.unwrap().to_string();
321004e86ffSlogin     // kdebug!("sys_unlink_at={path:?}");
322004e86ffSlogin     if (flag & (!(AT_REMOVEDIR as u64))) != 0_u64 {
323676b8ef6SMork         return SystemError::EINVAL.to_posix_errno() as u64;
324004e86ffSlogin     }
325004e86ffSlogin 
326004e86ffSlogin     if (flag & (AT_REMOVEDIR as u64)) > 0 {
327004e86ffSlogin         // kdebug!("rmdir");
328004e86ffSlogin         match do_remove_dir(&path) {
329004e86ffSlogin             Err(err) => {
330676b8ef6SMork                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
331676b8ef6SMork                 return err.to_posix_errno() as u64;
332004e86ffSlogin             }
333004e86ffSlogin             Ok(_) => {
334004e86ffSlogin                 return 0;
335004e86ffSlogin             }
336004e86ffSlogin         }
337004e86ffSlogin     }
338004e86ffSlogin 
339004e86ffSlogin     // kdebug!("rm");
340004e86ffSlogin     match do_unlink_at(&path, FileMode::from_bits_truncate(flag as u32)) {
341004e86ffSlogin         Err(err) => {
342676b8ef6SMork             kerror!("Failed to Remove Directory, Error Code = {:?}", err);
343676b8ef6SMork             return err.to_posix_errno() as u64;
344004e86ffSlogin         }
345004e86ffSlogin         Ok(_) => {
346004e86ffSlogin             return 0;
347004e86ffSlogin         }
348004e86ffSlogin     }
349004e86ffSlogin }
3502b771e32SGou Ngai 
3512b771e32SGou Ngai fn do_dup(oldfd: i32) -> Result<i32, SystemError> {
3522b771e32SGou Ngai     if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
3532b771e32SGou Ngai         // 获得当前文件描述符数组
3542b771e32SGou Ngai         // 确认oldfd是否有效
3552b771e32SGou Ngai         if FileDescriptorVec::validate_fd(oldfd) {
3562b771e32SGou Ngai             if let Some(file) = &fds.fds[oldfd as usize] {
3572b771e32SGou Ngai                 // 尝试获取对应的文件结构体
3582b771e32SGou Ngai                 let file_cp = (file).try_clone();
3592b771e32SGou Ngai                 if file_cp.is_none() {
3602b771e32SGou Ngai                     return Err(SystemError::EBADF);
3612b771e32SGou Ngai                 }
3622b771e32SGou Ngai                 let res = current_pcb().alloc_fd(*file_cp.unwrap(), None);
3632b771e32SGou Ngai                 // 申请文件描述符,并把文件对象存入其中
3642b771e32SGou Ngai                 return res;
3652b771e32SGou Ngai             }
3662b771e32SGou Ngai             // oldfd对应的文件不存在
3672b771e32SGou Ngai             return Err(SystemError::EBADF);
3682b771e32SGou Ngai         }
3692b771e32SGou Ngai         return Err(SystemError::EBADF);
3702b771e32SGou Ngai     } else {
3712b771e32SGou Ngai         return Err(SystemError::EMFILE);
3722b771e32SGou Ngai     }
3732b771e32SGou Ngai }
3742b771e32SGou Ngai 
3752b771e32SGou Ngai #[no_mangle]
3762b771e32SGou Ngai /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
3772b771e32SGou Ngai pub extern "C" fn sys_dup(regs: &pt_regs) -> u64 {
3782b771e32SGou Ngai     let fd: i32 = regs.r8 as i32;
3792b771e32SGou Ngai     let r = do_dup(fd);
3802b771e32SGou Ngai     if r.is_ok() {
3812b771e32SGou Ngai         return r.unwrap() as u64;
3822b771e32SGou Ngai     } else {
3832b771e32SGou Ngai         return r.unwrap_err().to_posix_errno() as u64;
3842b771e32SGou Ngai     }
3852b771e32SGou Ngai }
3862b771e32SGou Ngai 
3872b771e32SGou Ngai fn do_dup2(oldfd: i32, newfd: i32) -> Result<i32, SystemError> {
3882b771e32SGou Ngai     if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
3892b771e32SGou Ngai         // 获得当前文件描述符数组
3902b771e32SGou Ngai         if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
3912b771e32SGou Ngai             //确认oldfd, newid是否有效
3922b771e32SGou Ngai             if oldfd == newfd {
3932b771e32SGou Ngai                 // 若oldfd与newfd相等
3942b771e32SGou Ngai                 return Ok(newfd);
3952b771e32SGou Ngai             }
3962b771e32SGou Ngai 
3972b771e32SGou Ngai             if let Some(file) = &fds.fds[oldfd as usize] {
3982b771e32SGou Ngai                 if fds.fds[newfd as usize].is_some() {
3992b771e32SGou Ngai                     // close newfd
4002b771e32SGou Ngai                     if let Err(_) = current_pcb().drop_fd(newfd) {
4012b771e32SGou Ngai                         // An I/O error occurred while attempting to close fildes2.
4022b771e32SGou Ngai                         return Err(SystemError::EIO);
4032b771e32SGou Ngai                     }
4042b771e32SGou Ngai                 }
4052b771e32SGou Ngai 
4062b771e32SGou Ngai                 // 尝试获取对应的文件结构体
4072b771e32SGou Ngai                 let file_cp = file.try_clone();
4082b771e32SGou Ngai                 if file_cp.is_none() {
4092b771e32SGou Ngai                     return Err(SystemError::EBADF);
4102b771e32SGou Ngai                 }
4112b771e32SGou Ngai                 // 申请文件描述符,并把文件对象存入其中
4122b771e32SGou Ngai                 let res = current_pcb().alloc_fd(*file_cp.unwrap(), Some(newfd));
4132b771e32SGou Ngai 
4142b771e32SGou Ngai                 return res;
4152b771e32SGou Ngai             }
4162b771e32SGou Ngai             return Err(SystemError::EBADF);
4172b771e32SGou Ngai         } else {
4182b771e32SGou Ngai             return Err(SystemError::EBADF);
4192b771e32SGou Ngai         }
4202b771e32SGou Ngai     }
4212b771e32SGou Ngai     // 从pcb获取文件描述符数组失败
4222b771e32SGou Ngai     return Err(SystemError::EMFILE);
4232b771e32SGou Ngai }
4242b771e32SGou Ngai 
4252b771e32SGou Ngai #[no_mangle]
4262b771e32SGou Ngai /// @brief 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
4272b771e32SGou Ngai /// 并返回新复制的文件结构体对应的fd
4282b771e32SGou Ngai pub extern "C" fn sys_dup2(regs: &pt_regs) -> u64 {
4292b771e32SGou Ngai     let ofd = regs.r8 as i32;
4302b771e32SGou Ngai     let nfd = regs.r9 as i32;
4312b771e32SGou Ngai     let r = do_dup2(ofd, nfd);
4322b771e32SGou Ngai     if r.is_ok() {
4332b771e32SGou Ngai         return r.unwrap() as u64;
4342b771e32SGou Ngai     } else {
4352b771e32SGou Ngai         return r.unwrap_err().to_posix_errno() as u64;
4362b771e32SGou Ngai     }
4372b771e32SGou Ngai }
438*cde5492fSlogin 
439*cde5492fSlogin #[repr(C)]
440*cde5492fSlogin #[derive(Debug, Clone, Copy)]
441*cde5492fSlogin pub struct IoVec {
442*cde5492fSlogin     /// 缓冲区的起始地址
443*cde5492fSlogin     pub iov_base: *mut u8,
444*cde5492fSlogin     /// 缓冲区的长度
445*cde5492fSlogin     pub iov_len: usize,
446*cde5492fSlogin }
447*cde5492fSlogin 
448*cde5492fSlogin /// 用于存储多个来自用户空间的IoVec
449*cde5492fSlogin ///
450*cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
451*cde5492fSlogin /// TODO:支持分散读写
452*cde5492fSlogin #[derive(Debug)]
453*cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>);
454*cde5492fSlogin 
455*cde5492fSlogin impl IoVecs {
456*cde5492fSlogin     /// 从用户空间的IoVec中构造IoVecs
457*cde5492fSlogin     ///
458*cde5492fSlogin     /// @param iov 用户空间的IoVec
459*cde5492fSlogin     /// @param iovcnt 用户空间的IoVec的数量
460*cde5492fSlogin     /// @param readv 是否为readv系统调用
461*cde5492fSlogin     ///
462*cde5492fSlogin     /// @return 构造成功返回IoVecs,否则返回错误码
463*cde5492fSlogin     pub unsafe fn from_user(
464*cde5492fSlogin         iov: *const IoVec,
465*cde5492fSlogin         iovcnt: usize,
466*cde5492fSlogin         _readv: bool,
467*cde5492fSlogin     ) -> Result<Self, SystemError> {
468*cde5492fSlogin         // 检查iov指针所在空间是否合法
469*cde5492fSlogin         if !verify_area(
470*cde5492fSlogin             iov as usize as u64,
471*cde5492fSlogin             (iovcnt * core::mem::size_of::<IoVec>()) as u64,
472*cde5492fSlogin         ) {
473*cde5492fSlogin             return Err(SystemError::EFAULT);
474*cde5492fSlogin         }
475*cde5492fSlogin 
476*cde5492fSlogin         // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
477*cde5492fSlogin         let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
478*cde5492fSlogin 
479*cde5492fSlogin         let mut slices: Vec<&mut [u8]> = vec![];
480*cde5492fSlogin         slices.reserve(iovs.len());
481*cde5492fSlogin 
482*cde5492fSlogin         for iov in iovs.iter() {
483*cde5492fSlogin             if iov.iov_len == 0 {
484*cde5492fSlogin                 continue;
485*cde5492fSlogin             }
486*cde5492fSlogin 
487*cde5492fSlogin             if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) {
488*cde5492fSlogin                 return Err(SystemError::EFAULT);
489*cde5492fSlogin             }
490*cde5492fSlogin 
491*cde5492fSlogin             slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
492*cde5492fSlogin         }
493*cde5492fSlogin 
494*cde5492fSlogin         return Ok(Self(slices));
495*cde5492fSlogin     }
496*cde5492fSlogin 
497*cde5492fSlogin     /// @brief 将IoVecs中的数据聚合到一个缓冲区中
498*cde5492fSlogin     ///
499*cde5492fSlogin     /// @return 返回聚合后的缓冲区
500*cde5492fSlogin     pub fn gather(&self) -> Vec<u8> {
501*cde5492fSlogin         let mut buf = Vec::new();
502*cde5492fSlogin         for slice in self.0.iter() {
503*cde5492fSlogin             buf.extend_from_slice(slice);
504*cde5492fSlogin         }
505*cde5492fSlogin         return buf;
506*cde5492fSlogin     }
507*cde5492fSlogin 
508*cde5492fSlogin     /// @brief 将给定的数据分散写入到IoVecs中
509*cde5492fSlogin     pub fn scatter(&mut self, data: &[u8]) {
510*cde5492fSlogin         let mut data: &[u8] = data;
511*cde5492fSlogin         for slice in self.0.iter_mut() {
512*cde5492fSlogin             let len = core::cmp::min(slice.len(), data.len());
513*cde5492fSlogin             if len == 0 {
514*cde5492fSlogin                 continue;
515*cde5492fSlogin             }
516*cde5492fSlogin 
517*cde5492fSlogin             slice[..len].copy_from_slice(&data[..len]);
518*cde5492fSlogin             data = &data[len..];
519*cde5492fSlogin         }
520*cde5492fSlogin     }
521*cde5492fSlogin 
522*cde5492fSlogin     /// @brief 创建与IoVecs等长的缓冲区
523*cde5492fSlogin     ///
524*cde5492fSlogin     /// @param set_len 是否设置返回的Vec的len。
525*cde5492fSlogin     /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
526*cde5492fSlogin     /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
527*cde5492fSlogin     ///
528*cde5492fSlogin     /// @return 返回创建的缓冲区
529*cde5492fSlogin     pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
530*cde5492fSlogin         let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
531*cde5492fSlogin         let mut buf: Vec<u8> = Vec::with_capacity(total_len);
532*cde5492fSlogin 
533*cde5492fSlogin         if set_len {
534*cde5492fSlogin             unsafe {
535*cde5492fSlogin                 buf.set_len(total_len);
536*cde5492fSlogin             }
537*cde5492fSlogin         }
538*cde5492fSlogin         return buf;
539*cde5492fSlogin     }
540*cde5492fSlogin }
541