xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision 67b481888770c6469f572f244a4f97e42da77d1f)
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},
10*67b48188Shoumkh     time::TimeSpec,
11004e86ffSlogin };
12004e86ffSlogin 
13004e86ffSlogin use super::{
14ab5c8ca4Slogin     core::{do_mkdir, do_remove_dir, do_unlink_at},
156d81180bSLoGin     fcntl::{FcntlCommand, FD_CLOEXEC},
16004e86ffSlogin     file::{File, FileMode},
17ab5c8ca4Slogin     utils::rsplit_path,
18ab5c8ca4Slogin     Dirent, FileType, IndexNode, ROOT_INODE,
19004e86ffSlogin };
20004e86ffSlogin 
21ab5c8ca4Slogin pub const SEEK_SET: u32 = 0;
22ab5c8ca4Slogin pub const SEEK_CUR: u32 = 1;
23ab5c8ca4Slogin pub const SEEK_END: u32 = 2;
24ab5c8ca4Slogin pub const SEEK_MAX: u32 = 3;
25004e86ffSlogin 
26*67b48188Shoumkh bitflags! {
27*67b48188Shoumkh     /// 文件类型和权限
28*67b48188Shoumkh     pub struct ModeType: u32 {
29*67b48188Shoumkh         /// 掩码
30*67b48188Shoumkh         const S_IFMT = 0o0_170_000;
31*67b48188Shoumkh         /// 文件类型
32*67b48188Shoumkh         const S_IFSOCK = 0o140000;
33*67b48188Shoumkh         const S_IFLNK = 0o120000;
34*67b48188Shoumkh         const S_IFREG = 0o100000;
35*67b48188Shoumkh         const S_IFBLK = 0o060000;
36*67b48188Shoumkh         const S_IFDIR = 0o040000;
37*67b48188Shoumkh         const S_IFCHR = 0o020000;
38*67b48188Shoumkh         const S_IFIFO = 0o010000;
39*67b48188Shoumkh 
40*67b48188Shoumkh         const S_ISUID = 0o004000;
41*67b48188Shoumkh         const S_ISGID = 0o002000;
42*67b48188Shoumkh         const S_ISVTX = 0o001000;
43*67b48188Shoumkh         /// 文件用户权限
44*67b48188Shoumkh         const S_IRWXU = 0o0700;
45*67b48188Shoumkh         const S_IRUSR = 0o0400;
46*67b48188Shoumkh         const S_IWUSR = 0o0200;
47*67b48188Shoumkh         const S_IXUSR = 0o0100;
48*67b48188Shoumkh         /// 文件组权限
49*67b48188Shoumkh         const S_IRWXG = 0o0070;
50*67b48188Shoumkh         const S_IRGRP = 0o0040;
51*67b48188Shoumkh         const S_IWGRP = 0o0020;
52*67b48188Shoumkh         const S_IXGRP = 0o0010;
53*67b48188Shoumkh         /// 文件其他用户权限
54*67b48188Shoumkh         const S_IRWXO = 0o0007;
55*67b48188Shoumkh         const S_IROTH = 0o0004;
56*67b48188Shoumkh         const S_IWOTH = 0o0002;
57*67b48188Shoumkh         const S_IXOTH = 0o0001;
58*67b48188Shoumkh     }
59*67b48188Shoumkh }
60*67b48188Shoumkh 
61*67b48188Shoumkh #[repr(C)]
62*67b48188Shoumkh /// # 文件信息结构体
63*67b48188Shoumkh pub struct PosixKstat {
64*67b48188Shoumkh     /// 硬件设备ID
65*67b48188Shoumkh     dev_id: u64,
66*67b48188Shoumkh     /// inode号
67*67b48188Shoumkh     inode: u64,
68*67b48188Shoumkh     /// 硬链接数
69*67b48188Shoumkh     nlink: u64,
70*67b48188Shoumkh     /// 文件权限
71*67b48188Shoumkh     mode: ModeType,
72*67b48188Shoumkh     /// 所有者用户ID
73*67b48188Shoumkh     uid: i32,
74*67b48188Shoumkh     /// 所有者组ID
75*67b48188Shoumkh     gid: i32,
76*67b48188Shoumkh     /// 设备ID
77*67b48188Shoumkh     rdev: i64,
78*67b48188Shoumkh     /// 文件大小
79*67b48188Shoumkh     size: i64,
80*67b48188Shoumkh     /// 文件系统块大小
81*67b48188Shoumkh     blcok_size: i64,
82*67b48188Shoumkh     /// 分配的512B块数
83*67b48188Shoumkh     blocks: u64,
84*67b48188Shoumkh     /// 最后访问时间
85*67b48188Shoumkh     atime: TimeSpec,
86*67b48188Shoumkh     /// 最后修改时间
87*67b48188Shoumkh     mtime: TimeSpec,
88*67b48188Shoumkh     /// 最后状态变化时间
89*67b48188Shoumkh     ctime: TimeSpec,
90*67b48188Shoumkh     /// 用于填充结构体大小的空白数据
91*67b48188Shoumkh     pub _pad: [i8; 24],
92*67b48188Shoumkh }
93*67b48188Shoumkh impl PosixKstat {
94*67b48188Shoumkh     fn new() -> Self {
95*67b48188Shoumkh         Self {
96*67b48188Shoumkh             inode: 0,
97*67b48188Shoumkh             dev_id: 0,
98*67b48188Shoumkh             mode: ModeType { bits: 0 },
99*67b48188Shoumkh             nlink: 0,
100*67b48188Shoumkh             uid: 0,
101*67b48188Shoumkh             gid: 0,
102*67b48188Shoumkh             rdev: 0,
103*67b48188Shoumkh             size: 0,
104*67b48188Shoumkh             atime: TimeSpec {
105*67b48188Shoumkh                 tv_sec: 0,
106*67b48188Shoumkh                 tv_nsec: 0,
107*67b48188Shoumkh             },
108*67b48188Shoumkh             mtime: TimeSpec {
109*67b48188Shoumkh                 tv_sec: 0,
110*67b48188Shoumkh                 tv_nsec: 0,
111*67b48188Shoumkh             },
112*67b48188Shoumkh             ctime: TimeSpec {
113*67b48188Shoumkh                 tv_sec: 0,
114*67b48188Shoumkh                 tv_nsec: 0,
115*67b48188Shoumkh             },
116*67b48188Shoumkh             blcok_size: 0,
117*67b48188Shoumkh             blocks: 0,
118*67b48188Shoumkh             _pad: Default::default(),
119*67b48188Shoumkh         }
120*67b48188Shoumkh     }
121*67b48188Shoumkh }
122ab5c8ca4Slogin impl Syscall {
123ab5c8ca4Slogin     /// @brief 为当前进程打开一个文件
124ab5c8ca4Slogin     ///
125ab5c8ca4Slogin     /// @param path 文件路径
126ab5c8ca4Slogin     /// @param o_flags 打开文件的标志位
127ab5c8ca4Slogin     ///
128ab5c8ca4Slogin     /// @return 文件描述符编号,或者是错误码
129ab5c8ca4Slogin     pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
1306d81180bSLoGin         // kdebug!("open: path: {}, mode: {:?}", path, mode);
131ab5c8ca4Slogin         // 文件名过长
132ab5c8ca4Slogin         if path.len() > PAGE_4K_SIZE as usize {
133ab5c8ca4Slogin             return Err(SystemError::ENAMETOOLONG);
134ab5c8ca4Slogin         }
135ab5c8ca4Slogin 
136ab5c8ca4Slogin         let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
137ab5c8ca4Slogin 
138ab5c8ca4Slogin         let inode: Arc<dyn IndexNode> = if inode.is_err() {
139ab5c8ca4Slogin             let errno = inode.unwrap_err();
140ab5c8ca4Slogin             // 文件不存在,且需要创建
141ab5c8ca4Slogin             if mode.contains(FileMode::O_CREAT)
142ab5c8ca4Slogin                 && !mode.contains(FileMode::O_DIRECTORY)
143ab5c8ca4Slogin                 && errno == SystemError::ENOENT
144ab5c8ca4Slogin             {
145ab5c8ca4Slogin                 let (filename, parent_path) = rsplit_path(path);
146ab5c8ca4Slogin                 // 查找父目录
147ab5c8ca4Slogin                 let parent_inode: Arc<dyn IndexNode> =
148ab5c8ca4Slogin                     ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
149ab5c8ca4Slogin                 // 创建文件
150ab5c8ca4Slogin                 let inode: Arc<dyn IndexNode> =
151ab5c8ca4Slogin                     parent_inode.create(filename, FileType::File, 0o777)?;
152ab5c8ca4Slogin                 inode
153004e86ffSlogin             } else {
154ab5c8ca4Slogin                 // 不需要创建文件,因此返回错误码
155ab5c8ca4Slogin                 return Err(errno);
156004e86ffSlogin             }
157004e86ffSlogin         } else {
158ab5c8ca4Slogin             inode.unwrap()
159004e86ffSlogin         };
160004e86ffSlogin 
161ab5c8ca4Slogin         let file_type: FileType = inode.metadata()?.file_type;
162ab5c8ca4Slogin         // 如果要打开的是文件夹,而目标不是文件夹
163ab5c8ca4Slogin         if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
164ab5c8ca4Slogin             return Err(SystemError::ENOTDIR);
165004e86ffSlogin         }
166ab5c8ca4Slogin 
167ab5c8ca4Slogin         // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
168ab5c8ca4Slogin         if mode.contains(FileMode::O_TRUNC)
169ab5c8ca4Slogin             && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY))
170ab5c8ca4Slogin             && file_type == FileType::File
171ab5c8ca4Slogin         {
172ab5c8ca4Slogin             inode.truncate(0)?;
173ab5c8ca4Slogin         }
174ab5c8ca4Slogin 
175ab5c8ca4Slogin         // 创建文件对象
176ab5c8ca4Slogin         let mut file: File = File::new(inode, mode)?;
177ab5c8ca4Slogin 
178ab5c8ca4Slogin         // 打开模式为“追加”
179ab5c8ca4Slogin         if mode.contains(FileMode::O_APPEND) {
180ab5c8ca4Slogin             file.lseek(SeekFrom::SeekEnd(0))?;
181ab5c8ca4Slogin         }
182ab5c8ca4Slogin 
183ab5c8ca4Slogin         // 把文件对象存入pcb
1846d81180bSLoGin         let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize);
1856d81180bSLoGin         // kdebug!("open: fd: {:?}", r);
1866d81180bSLoGin         return r;
187ab5c8ca4Slogin     }
188ab5c8ca4Slogin 
189ab5c8ca4Slogin     /// @brief 关闭文件
190ab5c8ca4Slogin     ///
191ab5c8ca4Slogin     /// @param fd 文件描述符编号
192ab5c8ca4Slogin     ///
193ab5c8ca4Slogin     /// @return 成功返回0,失败返回错误码
194ab5c8ca4Slogin     pub fn close(fd: usize) -> Result<usize, SystemError> {
1956d81180bSLoGin         // kdebug!("syscall::close: fd: {}", fd);
196ab5c8ca4Slogin         return current_pcb().drop_fd(fd as i32).map(|_| 0);
197ab5c8ca4Slogin     }
198ab5c8ca4Slogin 
199ab5c8ca4Slogin     /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
200ab5c8ca4Slogin     ///
201ab5c8ca4Slogin     /// @param fd 文件描述符编号
202ab5c8ca4Slogin     /// @param buf 输出缓冲区。
203ab5c8ca4Slogin     ///
204ab5c8ca4Slogin     /// @return Ok(usize) 成功读取的数据的字节数
205ab5c8ca4Slogin     /// @return Err(SystemError) 读取失败,返回posix错误码
206ab5c8ca4Slogin     pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
2076d81180bSLoGin         // kdebug!("syscall::read: fd: {}, len={}", fd, buf.len());
208ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
209ab5c8ca4Slogin         if file.is_none() {
210ab5c8ca4Slogin             return Err(SystemError::EBADF);
211ab5c8ca4Slogin         }
212ab5c8ca4Slogin         let file: &mut File = file.unwrap();
213ab5c8ca4Slogin 
214ab5c8ca4Slogin         return file.read(buf.len(), buf);
215ab5c8ca4Slogin     }
216ab5c8ca4Slogin 
217ab5c8ca4Slogin     /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
218ab5c8ca4Slogin     ///
219ab5c8ca4Slogin     /// @param fd 文件描述符编号
220ab5c8ca4Slogin     /// @param buf 输入缓冲区。
221ab5c8ca4Slogin     ///
222ab5c8ca4Slogin     /// @return Ok(usize) 成功写入的数据的字节数
223ab5c8ca4Slogin     /// @return Err(SystemError) 写入失败,返回posix错误码
224ab5c8ca4Slogin     pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
2256d81180bSLoGin         // kdebug!("syscall::write: fd: {}, len={}", fd, buf.len());
226ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
227ab5c8ca4Slogin         if file.is_none() {
228ab5c8ca4Slogin             return Err(SystemError::EBADF);
229ab5c8ca4Slogin         }
230ab5c8ca4Slogin         let file: &mut File = file.unwrap();
231ab5c8ca4Slogin 
232ab5c8ca4Slogin         return file.write(buf.len(), buf);
233ab5c8ca4Slogin     }
234ab5c8ca4Slogin 
235ab5c8ca4Slogin     /// @brief 调整文件操作指针的位置
236ab5c8ca4Slogin     ///
237ab5c8ca4Slogin     /// @param fd 文件描述符编号
238ab5c8ca4Slogin     /// @param seek 调整的方式
239ab5c8ca4Slogin     ///
240ab5c8ca4Slogin     /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
241ab5c8ca4Slogin     /// @return Err(SystemError) 调整失败,返回posix错误码
242ab5c8ca4Slogin     pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
2436d81180bSLoGin         // kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek);
244ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
245ab5c8ca4Slogin         if file.is_none() {
246ab5c8ca4Slogin             return Err(SystemError::EBADF);
247ab5c8ca4Slogin         }
248ab5c8ca4Slogin         let file: &mut File = file.unwrap();
249ab5c8ca4Slogin         return file.lseek(seek);
250004e86ffSlogin     }
251004e86ffSlogin 
252004e86ffSlogin     /// @brief 切换工作目录
253004e86ffSlogin     ///
254004e86ffSlogin     /// @param dest_path 目标路径
255004e86ffSlogin     ///
256004e86ffSlogin     /// @return   返回码  描述
257004e86ffSlogin     ///      0       |          成功
258004e86ffSlogin     ///
259004e86ffSlogin     ///   EACCESS    |        权限不足
260004e86ffSlogin     ///
261004e86ffSlogin     ///    ELOOP     | 解析path时遇到路径循环
262004e86ffSlogin     ///
263004e86ffSlogin     /// ENAMETOOLONG |       路径名过长
264004e86ffSlogin     ///
265004e86ffSlogin     ///    ENOENT    |  目标文件或目录不存在
266004e86ffSlogin     ///
267004e86ffSlogin     ///    ENODIR    |  检索期间发现非目录项
268004e86ffSlogin     ///
269004e86ffSlogin     ///    ENOMEM    |      系统内存不足
270004e86ffSlogin     ///
271004e86ffSlogin     ///    EFAULT    |       错误的地址
272004e86ffSlogin     ///
273004e86ffSlogin     /// ENAMETOOLONG |        路径过长
274ab5c8ca4Slogin     pub fn chdir(dest_path: &str) -> Result<usize, SystemError> {
275ab5c8ca4Slogin         // Copy path to kernel space to avoid some security issues
276ab5c8ca4Slogin         let path: Box<&str> = Box::new(dest_path);
277004e86ffSlogin         let inode = match ROOT_INODE().lookup(&path) {
278004e86ffSlogin             Err(e) => {
279676b8ef6SMork                 kerror!("Change Directory Failed, Error = {:?}", e);
280ab5c8ca4Slogin                 return Err(SystemError::ENOENT);
281004e86ffSlogin             }
282004e86ffSlogin             Ok(i) => i,
283004e86ffSlogin         };
284004e86ffSlogin 
285004e86ffSlogin         match inode.metadata() {
286004e86ffSlogin             Err(e) => {
287676b8ef6SMork                 kerror!("INode Get MetaData Failed, Error = {:?}", e);
288ab5c8ca4Slogin                 return Err(SystemError::ENOENT);
289004e86ffSlogin             }
290004e86ffSlogin             Ok(i) => {
291004e86ffSlogin                 if let FileType::Dir = i.file_type {
292ab5c8ca4Slogin                     return Ok(0);
293004e86ffSlogin                 } else {
294ab5c8ca4Slogin                     return Err(SystemError::ENOTDIR);
295004e86ffSlogin                 }
296004e86ffSlogin             }
297004e86ffSlogin         }
298004e86ffSlogin     }
299004e86ffSlogin 
300004e86ffSlogin     /// @brief 获取目录中的数据
301004e86ffSlogin     ///
302ab5c8ca4Slogin     /// TODO: 这个函数的语义与Linux不一致,需要修改!!!
303ab5c8ca4Slogin     ///
304004e86ffSlogin     /// @param fd 文件描述符号
305ab5c8ca4Slogin     /// @param buf 输出缓冲区
306ab5c8ca4Slogin     ///
307ab5c8ca4Slogin     /// @return 成功返回读取的字节数,失败返回错误码
308ab5c8ca4Slogin     pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
309ab5c8ca4Slogin         let dirent =
310ab5c8ca4Slogin             unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?;
311004e86ffSlogin 
312004e86ffSlogin         if fd < 0 || fd as u32 > PROC_MAX_FD_NUM {
313ab5c8ca4Slogin             return Err(SystemError::EBADF);
314004e86ffSlogin         }
315004e86ffSlogin 
316004e86ffSlogin         // 获取fd
317004e86ffSlogin         let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) {
318004e86ffSlogin             None => {
319ab5c8ca4Slogin                 return Err(SystemError::EBADF);
320004e86ffSlogin             }
321004e86ffSlogin             Some(file) => file,
322004e86ffSlogin         };
323004e86ffSlogin         // kdebug!("file={file:?}");
324004e86ffSlogin 
325ab5c8ca4Slogin         return file.readdir(dirent).map(|x| x as usize);
326004e86ffSlogin     }
327004e86ffSlogin 
328004e86ffSlogin     /// @brief 创建文件夹
329004e86ffSlogin     ///
330004e86ffSlogin     /// @param path(r8) 路径 / mode(r9) 模式
331004e86ffSlogin     ///
332004e86ffSlogin     /// @return uint64_t 负数错误码 / 0表示成功
333ab5c8ca4Slogin     pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> {
334ab5c8ca4Slogin         return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
335004e86ffSlogin     }
336004e86ffSlogin 
337ab5c8ca4Slogin     /// **删除文件夹、取消文件的链接、删除文件的系统调用**
338004e86ffSlogin     ///
339ab5c8ca4Slogin     /// ## 参数
340004e86ffSlogin     ///
341ab5c8ca4Slogin     /// - `dirfd`:文件夹的文件描述符.目前暂未实现
342ab5c8ca4Slogin     /// - `pathname`:文件夹的路径
343ab5c8ca4Slogin     /// - `flags`:标志位
344004e86ffSlogin     ///
345004e86ffSlogin     ///
346ab5c8ca4Slogin     pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
347004e86ffSlogin         // kdebug!("sys_unlink_at={path:?}");
348ab5c8ca4Slogin         if (flags & (!AT_REMOVEDIR)) != 0 {
349ab5c8ca4Slogin             return Err(SystemError::EINVAL);
350004e86ffSlogin         }
351004e86ffSlogin 
352ab5c8ca4Slogin         if (flags & AT_REMOVEDIR) > 0 {
353004e86ffSlogin             // kdebug!("rmdir");
354ab5c8ca4Slogin             match do_remove_dir(&pathname) {
355004e86ffSlogin                 Err(err) => {
356676b8ef6SMork                     kerror!("Failed to Remove Directory, Error Code = {:?}", err);
357ab5c8ca4Slogin                     return Err(err);
358004e86ffSlogin                 }
359004e86ffSlogin                 Ok(_) => {
360ab5c8ca4Slogin                     return Ok(0);
361004e86ffSlogin                 }
362004e86ffSlogin             }
363004e86ffSlogin         }
364004e86ffSlogin 
365ab5c8ca4Slogin         match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) {
366004e86ffSlogin             Err(err) => {
367676b8ef6SMork                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
368ab5c8ca4Slogin                 return Err(err);
369004e86ffSlogin             }
370004e86ffSlogin             Ok(_) => {
371ab5c8ca4Slogin                 return Ok(0);
372004e86ffSlogin             }
373004e86ffSlogin         }
374004e86ffSlogin     }
3752b771e32SGou Ngai 
376ab5c8ca4Slogin     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
377ab5c8ca4Slogin     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
3782b771e32SGou Ngai         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
3792b771e32SGou Ngai             // 获得当前文件描述符数组
3802b771e32SGou Ngai             // 确认oldfd是否有效
3812b771e32SGou Ngai             if FileDescriptorVec::validate_fd(oldfd) {
3822b771e32SGou Ngai                 if let Some(file) = &fds.fds[oldfd as usize] {
3832b771e32SGou Ngai                     // 尝试获取对应的文件结构体
384ab5c8ca4Slogin                     let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?;
385ab5c8ca4Slogin 
3862b771e32SGou Ngai                     // 申请文件描述符,并把文件对象存入其中
387ab5c8ca4Slogin                     let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize);
3882b771e32SGou Ngai                     return res;
3892b771e32SGou Ngai                 }
3902b771e32SGou Ngai                 // oldfd对应的文件不存在
3912b771e32SGou Ngai                 return Err(SystemError::EBADF);
3922b771e32SGou Ngai             }
3932b771e32SGou Ngai             return Err(SystemError::EBADF);
3942b771e32SGou Ngai         } else {
3952b771e32SGou Ngai             return Err(SystemError::EMFILE);
3962b771e32SGou Ngai         }
3972b771e32SGou Ngai     }
3982b771e32SGou Ngai 
399ab5c8ca4Slogin     /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
400ab5c8ca4Slogin     /// 并返回新复制的文件结构体对应的fd.
401ab5c8ca4Slogin     /// 如果新fd已经打开,则会先关闭新fd.
402ab5c8ca4Slogin     ///
403ab5c8ca4Slogin     /// ## 参数
404ab5c8ca4Slogin     ///
405ab5c8ca4Slogin     /// - `oldfd`:旧文件描述符
406ab5c8ca4Slogin     /// - `newfd`:新文件描述符
407ab5c8ca4Slogin     ///
408ab5c8ca4Slogin     /// ## 返回值
409ab5c8ca4Slogin     ///
410ab5c8ca4Slogin     /// - 成功:新文件描述符
411ab5c8ca4Slogin     /// - 失败:错误码
412ab5c8ca4Slogin     pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> {
4132b771e32SGou Ngai         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
4142b771e32SGou Ngai             // 获得当前文件描述符数组
4152b771e32SGou Ngai             if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
4162b771e32SGou Ngai                 //确认oldfd, newid是否有效
4172b771e32SGou Ngai                 if oldfd == newfd {
4182b771e32SGou Ngai                     // 若oldfd与newfd相等
419ab5c8ca4Slogin                     return Ok(newfd as usize);
4202b771e32SGou Ngai                 }
4212b771e32SGou Ngai 
4222b771e32SGou Ngai                 if let Some(file) = &fds.fds[oldfd as usize] {
4232b771e32SGou Ngai                     if fds.fds[newfd as usize].is_some() {
4242b771e32SGou Ngai                         // close newfd
4252b771e32SGou Ngai                         if let Err(_) = current_pcb().drop_fd(newfd) {
4262b771e32SGou Ngai                             // An I/O error occurred while attempting to close fildes2.
4272b771e32SGou Ngai                             return Err(SystemError::EIO);
4282b771e32SGou Ngai                         }
4292b771e32SGou Ngai                     }
4302b771e32SGou Ngai 
4312b771e32SGou Ngai                     // 尝试获取对应的文件结构体
4322b771e32SGou Ngai                     let file_cp = file.try_clone();
4332b771e32SGou Ngai                     if file_cp.is_none() {
4342b771e32SGou Ngai                         return Err(SystemError::EBADF);
4352b771e32SGou Ngai                     }
4362b771e32SGou Ngai                     // 申请文件描述符,并把文件对象存入其中
437ab5c8ca4Slogin                     let res = current_pcb()
438ab5c8ca4Slogin                         .alloc_fd(*file_cp.unwrap(), Some(newfd))
439ab5c8ca4Slogin                         .map(|x| x as usize);
4402b771e32SGou Ngai 
4412b771e32SGou Ngai                     return res;
4422b771e32SGou Ngai                 }
4432b771e32SGou Ngai                 return Err(SystemError::EBADF);
4442b771e32SGou Ngai             } else {
4452b771e32SGou Ngai                 return Err(SystemError::EBADF);
4462b771e32SGou Ngai             }
4472b771e32SGou Ngai         }
4482b771e32SGou Ngai         // 从pcb获取文件描述符数组失败
4492b771e32SGou Ngai         return Err(SystemError::EMFILE);
4502b771e32SGou Ngai     }
4516d81180bSLoGin 
4526d81180bSLoGin     /// # fcntl
4536d81180bSLoGin     ///
4546d81180bSLoGin     /// ## 参数
4556d81180bSLoGin     ///
4566d81180bSLoGin     /// - `fd`:文件描述符
4576d81180bSLoGin     /// - `cmd`:命令
4586d81180bSLoGin     /// - `arg`:参数
4596d81180bSLoGin     pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> {
4606d81180bSLoGin         match cmd {
4616d81180bSLoGin             FcntlCommand::DupFd => {
4626d81180bSLoGin                 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
4636d81180bSLoGin                     return Err(SystemError::EBADF);
4646d81180bSLoGin                 }
4656d81180bSLoGin                 let arg = arg as usize;
4666d81180bSLoGin                 for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
4676d81180bSLoGin                     if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
4686d81180bSLoGin                         if fds.fds[i as usize].is_none() {
4696d81180bSLoGin                             return Self::dup2(fd, i as i32);
4706d81180bSLoGin                         }
4716d81180bSLoGin                     }
4726d81180bSLoGin                 }
4736d81180bSLoGin                 return Err(SystemError::EMFILE);
4746d81180bSLoGin             }
4756d81180bSLoGin             FcntlCommand::GetFd => {
4766d81180bSLoGin                 // Get file descriptor flags.
4776d81180bSLoGin 
4786d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
4796d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
4806d81180bSLoGin                         if let Some(file) = &fds.fds[fd as usize] {
4816d81180bSLoGin                             if file.close_on_exec() {
4826d81180bSLoGin                                 return Ok(FD_CLOEXEC as usize);
4836d81180bSLoGin                             }
4846d81180bSLoGin                         }
4856d81180bSLoGin                         return Err(SystemError::EBADF);
4866d81180bSLoGin                     }
4876d81180bSLoGin                 }
4886d81180bSLoGin                 return Err(SystemError::EBADF);
4896d81180bSLoGin             }
4906d81180bSLoGin             FcntlCommand::SetFd => {
4916d81180bSLoGin                 // Set file descriptor flags.
4926d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
4936d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
4946d81180bSLoGin                         if let Some(file) = &mut fds.fds[fd as usize] {
4956d81180bSLoGin                             let arg = arg as u32;
4966d81180bSLoGin                             if arg & FD_CLOEXEC != 0 {
4976d81180bSLoGin                                 file.set_close_on_exec(true);
4986d81180bSLoGin                             } else {
4996d81180bSLoGin                                 file.set_close_on_exec(false);
5006d81180bSLoGin                             }
5016d81180bSLoGin                             return Ok(0);
5026d81180bSLoGin                         }
5036d81180bSLoGin                         return Err(SystemError::EBADF);
5046d81180bSLoGin                     }
5056d81180bSLoGin                 }
5066d81180bSLoGin                 return Err(SystemError::EBADF);
5076d81180bSLoGin             }
5086d81180bSLoGin 
5096d81180bSLoGin             FcntlCommand::GetFlags => {
5106d81180bSLoGin                 // Get file status flags.
5116d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
5126d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
5136d81180bSLoGin                         if let Some(file) = &fds.fds[fd as usize] {
5146d81180bSLoGin                             return Ok(file.mode().bits() as usize);
5156d81180bSLoGin                         }
5166d81180bSLoGin                         return Err(SystemError::EBADF);
5176d81180bSLoGin                     }
5186d81180bSLoGin                 }
5196d81180bSLoGin                 return Err(SystemError::EBADF);
5206d81180bSLoGin             }
5216d81180bSLoGin             FcntlCommand::SetFlags => {
5226d81180bSLoGin                 // Set file status flags.
5236d81180bSLoGin                 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
5246d81180bSLoGin                     if FileDescriptorVec::validate_fd(fd) {
5256d81180bSLoGin                         if let Some(file) = &mut fds.fds[fd as usize] {
5266d81180bSLoGin                             let arg = arg as u32;
5276d81180bSLoGin                             let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?;
5286d81180bSLoGin                             file.set_mode(mode)?;
5296d81180bSLoGin                             return Ok(0);
5306d81180bSLoGin                         }
5316d81180bSLoGin                         return Err(SystemError::EBADF);
5326d81180bSLoGin                     }
5336d81180bSLoGin                 }
5346d81180bSLoGin                 return Err(SystemError::EBADF);
5356d81180bSLoGin             }
5366d81180bSLoGin             _ => {
5376d81180bSLoGin                 // TODO: unimplemented
5386d81180bSLoGin                 // 未实现的命令,返回0,不报错。
5396d81180bSLoGin 
5406d81180bSLoGin                 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
5416d81180bSLoGin                 return Ok(0);
5426d81180bSLoGin             }
5436d81180bSLoGin         }
5446d81180bSLoGin     }
5456d81180bSLoGin 
5466d81180bSLoGin     /// # ftruncate
5476d81180bSLoGin     ///
5486d81180bSLoGin     /// ## 描述
5496d81180bSLoGin     ///
5506d81180bSLoGin     /// 改变文件大小.
5516d81180bSLoGin     /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充.
5526d81180bSLoGin     /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小.
5536d81180bSLoGin     ///
5546d81180bSLoGin     /// ## 参数
5556d81180bSLoGin     ///
5566d81180bSLoGin     /// - `fd`:文件描述符
5576d81180bSLoGin     /// - `len`:文件大小
5586d81180bSLoGin     ///
5596d81180bSLoGin     /// ## 返回值
5606d81180bSLoGin     ///
5616d81180bSLoGin     /// 如果成功,返回0,否则返回错误码.
5626d81180bSLoGin     pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> {
5636d81180bSLoGin         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
5646d81180bSLoGin             if FileDescriptorVec::validate_fd(fd) {
5656d81180bSLoGin                 if let Some(file) = &mut fds.fds[fd as usize] {
5666d81180bSLoGin                     let r = file.ftruncate(len).map(|_| 0);
5676d81180bSLoGin                     return r;
5686d81180bSLoGin                 }
5696d81180bSLoGin                 return Err(SystemError::EBADF);
5706d81180bSLoGin             }
5716d81180bSLoGin         }
5726d81180bSLoGin         return Err(SystemError::EBADF);
5736d81180bSLoGin     }
574*67b48188Shoumkh     fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> {
575*67b48188Shoumkh         let cur = current_pcb();
576*67b48188Shoumkh         match cur.get_file_ref_by_fd(fd) {
577*67b48188Shoumkh             Some(file) => {
578*67b48188Shoumkh                 let mut kstat = PosixKstat::new();
579*67b48188Shoumkh                 // 获取文件信息
580*67b48188Shoumkh                 match file.metadata() {
581*67b48188Shoumkh                     Ok(metadata) => {
582*67b48188Shoumkh                         kstat.size = metadata.size as i64;
583*67b48188Shoumkh                         kstat.dev_id = metadata.dev_id as u64;
584*67b48188Shoumkh                         kstat.inode = metadata.inode_id as u64;
585*67b48188Shoumkh                         kstat.blcok_size = metadata.blk_size as i64;
586*67b48188Shoumkh                         kstat.blocks = metadata.blocks as u64;
587*67b48188Shoumkh 
588*67b48188Shoumkh                         kstat.atime.tv_sec = metadata.atime.tv_sec;
589*67b48188Shoumkh                         kstat.atime.tv_nsec = metadata.atime.tv_nsec;
590*67b48188Shoumkh                         kstat.mtime.tv_sec = metadata.mtime.tv_sec;
591*67b48188Shoumkh                         kstat.mtime.tv_nsec = metadata.mtime.tv_nsec;
592*67b48188Shoumkh                         kstat.ctime.tv_sec = metadata.ctime.tv_sec;
593*67b48188Shoumkh                         kstat.ctime.tv_nsec = metadata.ctime.tv_nsec;
594*67b48188Shoumkh 
595*67b48188Shoumkh                         kstat.nlink = metadata.nlinks as u64;
596*67b48188Shoumkh                         kstat.uid = metadata.uid as i32;
597*67b48188Shoumkh                         kstat.gid = metadata.gid as i32;
598*67b48188Shoumkh                         kstat.rdev = metadata.raw_dev as i64;
599*67b48188Shoumkh                         kstat.mode.bits = metadata.mode;
600*67b48188Shoumkh                         match file.file_type() {
601*67b48188Shoumkh                             FileType::File => kstat.mode.insert(ModeType::S_IFMT),
602*67b48188Shoumkh                             FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
603*67b48188Shoumkh                             FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
604*67b48188Shoumkh                             FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
605*67b48188Shoumkh                             FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK),
606*67b48188Shoumkh                             FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK),
607*67b48188Shoumkh                             FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO),
608*67b48188Shoumkh                         }
609*67b48188Shoumkh                     }
610*67b48188Shoumkh                     Err(e) => return Err(e),
611*67b48188Shoumkh                 }
612*67b48188Shoumkh 
613*67b48188Shoumkh                 return Ok(kstat);
614*67b48188Shoumkh             }
615*67b48188Shoumkh             None => {
616*67b48188Shoumkh                 return Err(SystemError::EINVAL);
617*67b48188Shoumkh             }
618*67b48188Shoumkh         }
619*67b48188Shoumkh     }
620*67b48188Shoumkh     pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
621*67b48188Shoumkh         match Self::do_fstat(fd) {
622*67b48188Shoumkh             Ok(kstat) => {
623*67b48188Shoumkh                 if usr_kstat.is_null() {
624*67b48188Shoumkh                     return Err(SystemError::EFAULT);
625*67b48188Shoumkh                 }
626*67b48188Shoumkh                 unsafe {
627*67b48188Shoumkh                     *usr_kstat = kstat;
628*67b48188Shoumkh                 }
629*67b48188Shoumkh                 return Ok(0);
630*67b48188Shoumkh             }
631*67b48188Shoumkh             Err(e) => return Err(e),
632*67b48188Shoumkh         }
633*67b48188Shoumkh     }
6342b771e32SGou Ngai }
635cde5492fSlogin 
636cde5492fSlogin #[repr(C)]
637cde5492fSlogin #[derive(Debug, Clone, Copy)]
638cde5492fSlogin pub struct IoVec {
639cde5492fSlogin     /// 缓冲区的起始地址
640cde5492fSlogin     pub iov_base: *mut u8,
641cde5492fSlogin     /// 缓冲区的长度
642cde5492fSlogin     pub iov_len: usize,
643cde5492fSlogin }
644cde5492fSlogin 
645cde5492fSlogin /// 用于存储多个来自用户空间的IoVec
646cde5492fSlogin ///
647cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
648cde5492fSlogin /// TODO:支持分散读写
649cde5492fSlogin #[derive(Debug)]
650cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>);
651cde5492fSlogin 
652cde5492fSlogin impl IoVecs {
653cde5492fSlogin     /// 从用户空间的IoVec中构造IoVecs
654cde5492fSlogin     ///
655cde5492fSlogin     /// @param iov 用户空间的IoVec
656cde5492fSlogin     /// @param iovcnt 用户空间的IoVec的数量
657cde5492fSlogin     /// @param readv 是否为readv系统调用
658cde5492fSlogin     ///
659cde5492fSlogin     /// @return 构造成功返回IoVecs,否则返回错误码
660cde5492fSlogin     pub unsafe fn from_user(
661cde5492fSlogin         iov: *const IoVec,
662cde5492fSlogin         iovcnt: usize,
663cde5492fSlogin         _readv: bool,
664cde5492fSlogin     ) -> Result<Self, SystemError> {
665cde5492fSlogin         // 检查iov指针所在空间是否合法
666cde5492fSlogin         if !verify_area(
667cde5492fSlogin             iov as usize as u64,
668cde5492fSlogin             (iovcnt * core::mem::size_of::<IoVec>()) as u64,
669cde5492fSlogin         ) {
670cde5492fSlogin             return Err(SystemError::EFAULT);
671cde5492fSlogin         }
672cde5492fSlogin 
673cde5492fSlogin         // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
674cde5492fSlogin         let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
675cde5492fSlogin 
676cde5492fSlogin         let mut slices: Vec<&mut [u8]> = vec![];
677cde5492fSlogin         slices.reserve(iovs.len());
678cde5492fSlogin 
679cde5492fSlogin         for iov in iovs.iter() {
680cde5492fSlogin             if iov.iov_len == 0 {
681cde5492fSlogin                 continue;
682cde5492fSlogin             }
683cde5492fSlogin 
684cde5492fSlogin             if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) {
685cde5492fSlogin                 return Err(SystemError::EFAULT);
686cde5492fSlogin             }
687cde5492fSlogin 
688cde5492fSlogin             slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
689cde5492fSlogin         }
690cde5492fSlogin 
691cde5492fSlogin         return Ok(Self(slices));
692cde5492fSlogin     }
693cde5492fSlogin 
694cde5492fSlogin     /// @brief 将IoVecs中的数据聚合到一个缓冲区中
695cde5492fSlogin     ///
696cde5492fSlogin     /// @return 返回聚合后的缓冲区
697cde5492fSlogin     pub fn gather(&self) -> Vec<u8> {
698cde5492fSlogin         let mut buf = Vec::new();
699cde5492fSlogin         for slice in self.0.iter() {
700cde5492fSlogin             buf.extend_from_slice(slice);
701cde5492fSlogin         }
702cde5492fSlogin         return buf;
703cde5492fSlogin     }
704cde5492fSlogin 
705cde5492fSlogin     /// @brief 将给定的数据分散写入到IoVecs中
706cde5492fSlogin     pub fn scatter(&mut self, data: &[u8]) {
707cde5492fSlogin         let mut data: &[u8] = data;
708cde5492fSlogin         for slice in self.0.iter_mut() {
709cde5492fSlogin             let len = core::cmp::min(slice.len(), data.len());
710cde5492fSlogin             if len == 0 {
711cde5492fSlogin                 continue;
712cde5492fSlogin             }
713cde5492fSlogin 
714cde5492fSlogin             slice[..len].copy_from_slice(&data[..len]);
715cde5492fSlogin             data = &data[len..];
716cde5492fSlogin         }
717cde5492fSlogin     }
718cde5492fSlogin 
719cde5492fSlogin     /// @brief 创建与IoVecs等长的缓冲区
720cde5492fSlogin     ///
721cde5492fSlogin     /// @param set_len 是否设置返回的Vec的len。
722cde5492fSlogin     /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
723cde5492fSlogin     /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
724cde5492fSlogin     ///
725cde5492fSlogin     /// @return 返回创建的缓冲区
726cde5492fSlogin     pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
727cde5492fSlogin         let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
728cde5492fSlogin         let mut buf: Vec<u8> = Vec::with_capacity(total_len);
729cde5492fSlogin 
730cde5492fSlogin         if set_len {
731cde5492fSlogin             unsafe {
732cde5492fSlogin                 buf.set_len(total_len);
733cde5492fSlogin             }
734cde5492fSlogin         }
735cde5492fSlogin         return buf;
736cde5492fSlogin     }
737cde5492fSlogin }
738