xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision 2b771e32f5795e0fdda458e3bb2651ef6b9673ac)
1004e86ffSlogin use core::ffi::{c_char, CStr};
2004e86ffSlogin 
384407d36Slogin use alloc::{boxed::Box, string::ToString};
4004e86ffSlogin 
5004e86ffSlogin use crate::{
6004e86ffSlogin     arch::asm::{current::current_pcb, ptrace::user_mode},
7*2b771e32SGou Ngai     filesystem::vfs::file::FileDescriptorVec,
8004e86ffSlogin     include::bindings::bindings::{
9*2b771e32SGou Ngai         pt_regs, verify_area, AT_REMOVEDIR, PAGE_2M_SIZE, PAGE_4K_SIZE, PROC_MAX_FD_NUM, SEEK_CUR,
10*2b771e32SGou Ngai         SEEK_END, SEEK_MAX, SEEK_SET,
11004e86ffSlogin     },
12004e86ffSlogin     io::SeekFrom,
13*2b771e32SGou Ngai     kerror,
14*2b771e32SGou 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 }
350*2b771e32SGou Ngai 
351*2b771e32SGou Ngai fn do_dup(oldfd: i32) -> Result<i32, SystemError> {
352*2b771e32SGou Ngai     if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
353*2b771e32SGou Ngai         // 获得当前文件描述符数组
354*2b771e32SGou Ngai         // 确认oldfd是否有效
355*2b771e32SGou Ngai         if FileDescriptorVec::validate_fd(oldfd) {
356*2b771e32SGou Ngai             if let Some(file) = &fds.fds[oldfd as usize] {
357*2b771e32SGou Ngai                 // 尝试获取对应的文件结构体
358*2b771e32SGou Ngai                 let file_cp = (file).try_clone();
359*2b771e32SGou Ngai                 if file_cp.is_none() {
360*2b771e32SGou Ngai                     return Err(SystemError::EBADF);
361*2b771e32SGou Ngai                 }
362*2b771e32SGou Ngai                 let res = current_pcb().alloc_fd(*file_cp.unwrap(), None);
363*2b771e32SGou Ngai                 // 申请文件描述符,并把文件对象存入其中
364*2b771e32SGou Ngai                 return res;
365*2b771e32SGou Ngai             }
366*2b771e32SGou Ngai             // oldfd对应的文件不存在
367*2b771e32SGou Ngai             return Err(SystemError::EBADF);
368*2b771e32SGou Ngai         }
369*2b771e32SGou Ngai         return Err(SystemError::EBADF);
370*2b771e32SGou Ngai     } else {
371*2b771e32SGou Ngai         return Err(SystemError::EMFILE);
372*2b771e32SGou Ngai     }
373*2b771e32SGou Ngai }
374*2b771e32SGou Ngai 
375*2b771e32SGou Ngai #[no_mangle]
376*2b771e32SGou Ngai /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
377*2b771e32SGou Ngai pub extern "C" fn sys_dup(regs: &pt_regs) -> u64 {
378*2b771e32SGou Ngai     let fd: i32 = regs.r8 as i32;
379*2b771e32SGou Ngai     let r = do_dup(fd);
380*2b771e32SGou Ngai     if r.is_ok() {
381*2b771e32SGou Ngai         return r.unwrap() as u64;
382*2b771e32SGou Ngai     } else {
383*2b771e32SGou Ngai         return r.unwrap_err().to_posix_errno() as u64;
384*2b771e32SGou Ngai     }
385*2b771e32SGou Ngai }
386*2b771e32SGou Ngai 
387*2b771e32SGou Ngai fn do_dup2(oldfd: i32, newfd: i32) -> Result<i32, SystemError> {
388*2b771e32SGou Ngai     if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
389*2b771e32SGou Ngai         // 获得当前文件描述符数组
390*2b771e32SGou Ngai         if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
391*2b771e32SGou Ngai             //确认oldfd, newid是否有效
392*2b771e32SGou Ngai             if oldfd == newfd {
393*2b771e32SGou Ngai                 // 若oldfd与newfd相等
394*2b771e32SGou Ngai                 return Ok(newfd);
395*2b771e32SGou Ngai             }
396*2b771e32SGou Ngai 
397*2b771e32SGou Ngai             if let Some(file) = &fds.fds[oldfd as usize] {
398*2b771e32SGou Ngai                 if fds.fds[newfd as usize].is_some() {
399*2b771e32SGou Ngai                     // close newfd
400*2b771e32SGou Ngai                     if let Err(_) = current_pcb().drop_fd(newfd) {
401*2b771e32SGou Ngai                         // An I/O error occurred while attempting to close fildes2.
402*2b771e32SGou Ngai                         return Err(SystemError::EIO);
403*2b771e32SGou Ngai                     }
404*2b771e32SGou Ngai                 }
405*2b771e32SGou Ngai 
406*2b771e32SGou Ngai                 // 尝试获取对应的文件结构体
407*2b771e32SGou Ngai                 let file_cp = file.try_clone();
408*2b771e32SGou Ngai                 if file_cp.is_none() {
409*2b771e32SGou Ngai                     return Err(SystemError::EBADF);
410*2b771e32SGou Ngai                 }
411*2b771e32SGou Ngai                 // 申请文件描述符,并把文件对象存入其中
412*2b771e32SGou Ngai                 let res = current_pcb().alloc_fd(*file_cp.unwrap(), Some(newfd));
413*2b771e32SGou Ngai 
414*2b771e32SGou Ngai                 return res;
415*2b771e32SGou Ngai             }
416*2b771e32SGou Ngai             return Err(SystemError::EBADF);
417*2b771e32SGou Ngai         } else {
418*2b771e32SGou Ngai             return Err(SystemError::EBADF);
419*2b771e32SGou Ngai         }
420*2b771e32SGou Ngai     }
421*2b771e32SGou Ngai     // 从pcb获取文件描述符数组失败
422*2b771e32SGou Ngai     return Err(SystemError::EMFILE);
423*2b771e32SGou Ngai }
424*2b771e32SGou Ngai 
425*2b771e32SGou Ngai #[no_mangle]
426*2b771e32SGou Ngai /// @brief 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
427*2b771e32SGou Ngai /// 并返回新复制的文件结构体对应的fd
428*2b771e32SGou Ngai pub extern "C" fn sys_dup2(regs: &pt_regs) -> u64 {
429*2b771e32SGou Ngai     let ofd = regs.r8 as i32;
430*2b771e32SGou Ngai     let nfd = regs.r9 as i32;
431*2b771e32SGou Ngai     let r = do_dup2(ofd, nfd);
432*2b771e32SGou Ngai     if r.is_ok() {
433*2b771e32SGou Ngai         return r.unwrap() as u64;
434*2b771e32SGou Ngai     } else {
435*2b771e32SGou Ngai         return r.unwrap_err().to_posix_errno() as u64;
436*2b771e32SGou Ngai     }
437*2b771e32SGou Ngai }
438