xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision 1496ba7b24a5e6954291ca9643b9f3cec567479a)
1 use alloc::{
2     string::{String, ToString},
3     sync::Arc,
4     vec::Vec,
5 };
6 
7 use crate::{
8     driver::base::block::SeekFrom,
9     filesystem::vfs::file::FileDescriptorVec,
10     include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM},
11     kerror,
12     libs::rwlock::RwLockWriteGuard,
13     mm::VirtAddr,
14     process::ProcessManager,
15     syscall::{Syscall, SystemError},
16     time::TimeSpec,
17 };
18 
19 use super::{
20     core::{do_mkdir, do_remove_dir, do_unlink_at},
21     fcntl::{FcntlCommand, FD_CLOEXEC},
22     file::{File, FileMode},
23     utils::rsplit_path,
24     Dirent, FileType, IndexNode, ROOT_INODE,
25 };
26 
27 pub const SEEK_SET: u32 = 0;
28 pub const SEEK_CUR: u32 = 1;
29 pub const SEEK_END: u32 = 2;
30 pub const SEEK_MAX: u32 = 3;
31 
32 bitflags! {
33     /// 文件类型和权限
34     pub struct ModeType: u32 {
35         /// 掩码
36         const S_IFMT = 0o0_170_000;
37         /// 文件类型
38         const S_IFSOCK = 0o140000;
39         const S_IFLNK = 0o120000;
40         const S_IFREG = 0o100000;
41         const S_IFBLK = 0o060000;
42         const S_IFDIR = 0o040000;
43         const S_IFCHR = 0o020000;
44         const S_IFIFO = 0o010000;
45 
46         const S_ISUID = 0o004000;
47         const S_ISGID = 0o002000;
48         const S_ISVTX = 0o001000;
49         /// 文件用户权限
50         const S_IRWXU = 0o0700;
51         const S_IRUSR = 0o0400;
52         const S_IWUSR = 0o0200;
53         const S_IXUSR = 0o0100;
54         /// 文件组权限
55         const S_IRWXG = 0o0070;
56         const S_IRGRP = 0o0040;
57         const S_IWGRP = 0o0020;
58         const S_IXGRP = 0o0010;
59         /// 文件其他用户权限
60         const S_IRWXO = 0o0007;
61         const S_IROTH = 0o0004;
62         const S_IWOTH = 0o0002;
63         const S_IXOTH = 0o0001;
64     }
65 }
66 
67 #[repr(C)]
68 /// # 文件信息结构体
69 pub struct PosixKstat {
70     /// 硬件设备ID
71     dev_id: u64,
72     /// inode号
73     inode: u64,
74     /// 硬链接数
75     nlink: u64,
76     /// 文件权限
77     mode: ModeType,
78     /// 所有者用户ID
79     uid: i32,
80     /// 所有者组ID
81     gid: i32,
82     /// 设备ID
83     rdev: i64,
84     /// 文件大小
85     size: i64,
86     /// 文件系统块大小
87     blcok_size: i64,
88     /// 分配的512B块数
89     blocks: u64,
90     /// 最后访问时间
91     atime: TimeSpec,
92     /// 最后修改时间
93     mtime: TimeSpec,
94     /// 最后状态变化时间
95     ctime: TimeSpec,
96     /// 用于填充结构体大小的空白数据
97     pub _pad: [i8; 24],
98 }
99 impl PosixKstat {
100     fn new() -> Self {
101         Self {
102             inode: 0,
103             dev_id: 0,
104             mode: ModeType { bits: 0 },
105             nlink: 0,
106             uid: 0,
107             gid: 0,
108             rdev: 0,
109             size: 0,
110             atime: TimeSpec {
111                 tv_sec: 0,
112                 tv_nsec: 0,
113             },
114             mtime: TimeSpec {
115                 tv_sec: 0,
116                 tv_nsec: 0,
117             },
118             ctime: TimeSpec {
119                 tv_sec: 0,
120                 tv_nsec: 0,
121             },
122             blcok_size: 0,
123             blocks: 0,
124             _pad: Default::default(),
125         }
126     }
127 }
128 impl Syscall {
129     /// @brief 为当前进程打开一个文件
130     ///
131     /// @param path 文件路径
132     /// @param o_flags 打开文件的标志位
133     ///
134     /// @return 文件描述符编号,或者是错误码
135     pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
136         // kdebug!("open: path: {}, mode: {:?}", path, mode);
137 
138         // 文件名过长
139         if path.len() > PAGE_4K_SIZE as usize {
140             return Err(SystemError::ENAMETOOLONG);
141         }
142 
143         let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
144 
145         let inode: Arc<dyn IndexNode> = if inode.is_err() {
146             let errno = inode.unwrap_err();
147             // 文件不存在,且需要创建
148             if mode.contains(FileMode::O_CREAT)
149                 && !mode.contains(FileMode::O_DIRECTORY)
150                 && errno == SystemError::ENOENT
151             {
152                 let (filename, parent_path) = rsplit_path(path);
153                 // 查找父目录
154                 let parent_inode: Arc<dyn IndexNode> =
155                     ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
156                 // 创建文件
157                 let inode: Arc<dyn IndexNode> =
158                     parent_inode.create(filename, FileType::File, 0o777)?;
159                 inode
160             } else {
161                 // 不需要创建文件,因此返回错误码
162                 return Err(errno);
163             }
164         } else {
165             inode.unwrap()
166         };
167 
168         let file_type: FileType = inode.metadata()?.file_type;
169         // 如果要打开的是文件夹,而目标不是文件夹
170         if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
171             return Err(SystemError::ENOTDIR);
172         }
173 
174         // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
175         if mode.contains(FileMode::O_TRUNC)
176             && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY))
177             && file_type == FileType::File
178         {
179             inode.truncate(0)?;
180         }
181 
182         // 创建文件对象
183         let mut file: File = File::new(inode, mode)?;
184 
185         // 打开模式为“追加”
186         if mode.contains(FileMode::O_APPEND) {
187             file.lseek(SeekFrom::SeekEnd(0))?;
188         }
189 
190         // 把文件对象存入pcb
191         let r = ProcessManager::current_pcb()
192             .fd_table()
193             .write()
194             .alloc_fd(file, None)
195             .map(|fd| fd as usize);
196 
197         return r;
198     }
199 
200     /// @brief 关闭文件
201     ///
202     /// @param fd 文件描述符编号
203     ///
204     /// @return 成功返回0,失败返回错误码
205     pub fn close(fd: usize) -> Result<usize, SystemError> {
206         let binding = ProcessManager::current_pcb().fd_table();
207         let mut fd_table_guard = binding.write();
208 
209         return fd_table_guard.drop_fd(fd as i32).map(|_| 0);
210     }
211 
212     /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
213     ///
214     /// @param fd 文件描述符编号
215     /// @param buf 输出缓冲区。
216     ///
217     /// @return Ok(usize) 成功读取的数据的字节数
218     /// @return Err(SystemError) 读取失败,返回posix错误码
219     pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
220         let binding = ProcessManager::current_pcb().fd_table();
221         let fd_table_guard = binding.read();
222 
223         let file = fd_table_guard.get_file_by_fd(fd);
224         if file.is_none() {
225             return Err(SystemError::EBADF);
226         }
227         // drop guard 以避免无法调度的问题
228         drop(fd_table_guard);
229         let file = file.unwrap();
230 
231         return file.lock_no_preempt().read(buf.len(), buf);
232     }
233 
234     /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
235     ///
236     /// @param fd 文件描述符编号
237     /// @param buf 输入缓冲区。
238     ///
239     /// @return Ok(usize) 成功写入的数据的字节数
240     /// @return Err(SystemError) 写入失败,返回posix错误码
241     pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
242         let binding = ProcessManager::current_pcb().fd_table();
243         let fd_table_guard = binding.read();
244 
245         let file = fd_table_guard
246             .get_file_by_fd(fd)
247             .ok_or(SystemError::EBADF)?;
248 
249         // drop guard 以避免无法调度的问题
250         drop(fd_table_guard);
251         return file.lock_no_preempt().write(buf.len(), buf);
252     }
253 
254     /// @brief 调整文件操作指针的位置
255     ///
256     /// @param fd 文件描述符编号
257     /// @param seek 调整的方式
258     ///
259     /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
260     /// @return Err(SystemError) 调整失败,返回posix错误码
261     pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
262         let binding = ProcessManager::current_pcb().fd_table();
263         let fd_table_guard = binding.read();
264         let file = fd_table_guard
265             .get_file_by_fd(fd)
266             .ok_or(SystemError::EBADF)?;
267 
268         // drop guard 以避免无法调度的问题
269         drop(fd_table_guard);
270         return file.lock_no_preempt().lseek(seek);
271     }
272 
273     /// @brief 切换工作目录
274     ///
275     /// @param dest_path 目标路径
276     ///
277     /// @return   返回码  描述
278     ///      0       |          成功
279     ///
280     ///   EACCESS    |        权限不足
281     ///
282     ///    ELOOP     | 解析path时遇到路径循环
283     ///
284     /// ENAMETOOLONG |       路径名过长
285     ///
286     ///    ENOENT    |  目标文件或目录不存在
287     ///
288     ///    ENODIR    |  检索期间发现非目录项
289     ///
290     ///    ENOMEM    |      系统内存不足
291     ///
292     ///    EFAULT    |       错误的地址
293     ///
294     /// ENAMETOOLONG |        路径过长
295     pub fn chdir(dest_path: &str) -> Result<usize, SystemError> {
296         let proc = ProcessManager::current_pcb();
297         // Copy path to kernel space to avoid some security issues
298         let path = dest_path.to_string();
299         let mut new_path = String::from("");
300         if path.len() > 0 {
301             let cwd = match path.as_bytes()[0] {
302                 b'/' => String::from("/"),
303                 _ => proc.basic().cwd(),
304             };
305             let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect();
306             let path_split = path.split("/").filter(|&x| x != "");
307             for seg in path_split {
308                 if seg == ".." {
309                     cwd_vec.pop();
310                 } else if seg == "." {
311                     // 当前目录
312                 } else {
313                     cwd_vec.push(seg);
314                 }
315             }
316             //proc.basic().set_path(String::from(""));
317             for seg in cwd_vec {
318                 new_path.push_str("/");
319                 new_path.push_str(seg);
320             }
321             if new_path == "" {
322                 new_path = String::from("/");
323             }
324         }
325         let inode = match ROOT_INODE().lookup(&new_path) {
326             Err(e) => {
327                 kerror!("Change Directory Failed, Error = {:?}", e);
328                 return Err(SystemError::ENOENT);
329             }
330             Ok(i) => i,
331         };
332         let metadata = inode.metadata()?;
333         if metadata.file_type == FileType::Dir {
334             proc.basic_mut().set_cwd(String::from(new_path));
335             return Ok(0);
336         } else {
337             return Err(SystemError::ENOTDIR);
338         }
339     }
340 
341     /// @brief 获取当前进程的工作目录路径
342     ///
343     /// @param buf 指向缓冲区的指针
344     /// @param size 缓冲区的大小
345     ///
346     /// @return 成功,返回的指针指向包含工作目录路径的字符串
347     /// @return 错误,没有足够的空间
348     pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> {
349         let proc = ProcessManager::current_pcb();
350         let cwd = proc.basic().cwd();
351 
352         let cwd_bytes = cwd.as_bytes();
353         let cwd_len = cwd_bytes.len();
354         if cwd_len + 1 > buf.len() {
355             return Err(SystemError::ENOMEM);
356         }
357         buf[..cwd_len].copy_from_slice(cwd_bytes);
358         buf[cwd_len] = 0;
359 
360         return Ok(VirtAddr::new(buf.as_ptr() as usize));
361     }
362 
363     /// @brief 获取目录中的数据
364     ///
365     /// TODO: 这个函数的语义与Linux不一致,需要修改!!!
366     ///
367     /// @param fd 文件描述符号
368     /// @param buf 输出缓冲区
369     ///
370     /// @return 成功返回读取的字节数,失败返回错误码
371     pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
372         let dirent =
373             unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?;
374 
375         if fd < 0 || fd as u32 > PROC_MAX_FD_NUM {
376             return Err(SystemError::EBADF);
377         }
378 
379         // 获取fd
380         let binding = ProcessManager::current_pcb().fd_table();
381         let fd_table_guard = binding.read();
382         let file = fd_table_guard
383             .get_file_by_fd(fd)
384             .ok_or(SystemError::EBADF)?;
385 
386         // drop guard 以避免无法调度的问题
387         drop(fd_table_guard);
388         return file.lock_no_preempt().readdir(dirent).map(|x| x as usize);
389     }
390 
391     /// @brief 创建文件夹
392     ///
393     /// @param path(r8) 路径 / mode(r9) 模式
394     ///
395     /// @return uint64_t 负数错误码 / 0表示成功
396     pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> {
397         return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
398     }
399 
400     /// **删除文件夹、取消文件的链接、删除文件的系统调用**
401     ///
402     /// ## 参数
403     ///
404     /// - `dirfd`:文件夹的文件描述符.目前暂未实现
405     /// - `pathname`:文件夹的路径
406     /// - `flags`:标志位
407     ///
408     ///
409     pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
410         // kdebug!("sys_unlink_at={path:?}");
411         if (flags & (!AT_REMOVEDIR)) != 0 {
412             return Err(SystemError::EINVAL);
413         }
414 
415         if (flags & AT_REMOVEDIR) > 0 {
416             // kdebug!("rmdir");
417             match do_remove_dir(&pathname) {
418                 Err(err) => {
419                     kerror!("Failed to Remove Directory, Error Code = {:?}", err);
420                     return Err(err);
421                 }
422                 Ok(_) => {
423                     return Ok(0);
424                 }
425             }
426         }
427 
428         match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) {
429             Err(err) => {
430                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
431                 return Err(err);
432             }
433             Ok(_) => {
434                 return Ok(0);
435             }
436         }
437     }
438 
439     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
440     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
441         let binding = ProcessManager::current_pcb().fd_table();
442         let mut fd_table_guard = binding.write();
443 
444         let old_file = fd_table_guard
445             .get_file_by_fd(oldfd)
446             .ok_or(SystemError::EBADF)?;
447 
448         let new_file = old_file
449             .lock_no_preempt()
450             .try_clone()
451             .ok_or(SystemError::EBADF)?;
452         // 申请文件描述符,并把文件对象存入其中
453         let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize);
454         return res;
455     }
456 
457     /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
458     /// 并返回新复制的文件结构体对应的fd.
459     /// 如果新fd已经打开,则会先关闭新fd.
460     ///
461     /// ## 参数
462     ///
463     /// - `oldfd`:旧文件描述符
464     /// - `newfd`:新文件描述符
465     ///
466     /// ## 返回值
467     ///
468     /// - 成功:新文件描述符
469     /// - 失败:错误码
470     pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> {
471         let binding = ProcessManager::current_pcb().fd_table();
472         let mut fd_table_guard = binding.write();
473         return Self::do_dup2(oldfd, newfd, &mut fd_table_guard);
474     }
475 
476     fn do_dup2(
477         oldfd: i32,
478         newfd: i32,
479         fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>,
480     ) -> Result<usize, SystemError> {
481         // 确认oldfd, newid是否有效
482         if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) {
483             return Err(SystemError::EBADF);
484         }
485 
486         if oldfd == newfd {
487             // 若oldfd与newfd相等
488             return Ok(newfd as usize);
489         }
490         let new_exists = fd_table_guard.get_file_by_fd(newfd).is_some();
491         if new_exists {
492             // close newfd
493             if let Err(_) = fd_table_guard.drop_fd(newfd) {
494                 // An I/O error occurred while attempting to close fildes2.
495                 return Err(SystemError::EIO);
496             }
497         }
498 
499         let old_file = fd_table_guard
500             .get_file_by_fd(oldfd)
501             .ok_or(SystemError::EBADF)?;
502         let new_file = old_file
503             .lock_no_preempt()
504             .try_clone()
505             .ok_or(SystemError::EBADF)?;
506         // 申请文件描述符,并把文件对象存入其中
507         let res = fd_table_guard
508             .alloc_fd(new_file, Some(newfd))
509             .map(|x| x as usize);
510         return res;
511     }
512 
513     /// # fcntl
514     ///
515     /// ## 参数
516     ///
517     /// - `fd`:文件描述符
518     /// - `cmd`:命令
519     /// - `arg`:参数
520     pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> {
521         match cmd {
522             FcntlCommand::DupFd => {
523                 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
524                     return Err(SystemError::EBADF);
525                 }
526                 let arg = arg as usize;
527                 for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
528                     let binding = ProcessManager::current_pcb().fd_table();
529                     let mut fd_table_guard = binding.write();
530                     if fd_table_guard.get_file_by_fd(fd).is_none() {
531                         return Self::do_dup2(fd, i as i32, &mut fd_table_guard);
532                     }
533                 }
534                 return Err(SystemError::EMFILE);
535             }
536             FcntlCommand::GetFd => {
537                 // Get file descriptor flags.
538                 let binding = ProcessManager::current_pcb().fd_table();
539                 let fd_table_guard = binding.read();
540                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
541                     // drop guard 以避免无法调度的问题
542                     drop(fd_table_guard);
543 
544                     if file.lock().close_on_exec() {
545                         return Ok(FD_CLOEXEC as usize);
546                     }
547                 }
548                 return Err(SystemError::EBADF);
549             }
550             FcntlCommand::SetFd => {
551                 // Set file descriptor flags.
552                 let binding = ProcessManager::current_pcb().fd_table();
553                 let fd_table_guard = binding.write();
554 
555                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
556                     // drop guard 以避免无法调度的问题
557                     drop(fd_table_guard);
558                     let arg = arg as u32;
559                     if arg & FD_CLOEXEC != 0 {
560                         file.lock().set_close_on_exec(true);
561                     } else {
562                         file.lock().set_close_on_exec(false);
563                     }
564                     return Ok(0);
565                 }
566                 return Err(SystemError::EBADF);
567             }
568 
569             FcntlCommand::GetFlags => {
570                 // Get file status flags.
571                 let binding = ProcessManager::current_pcb().fd_table();
572                 let fd_table_guard = binding.read();
573 
574                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
575                     // drop guard 以避免无法调度的问题
576                     drop(fd_table_guard);
577                     return Ok(file.lock_no_preempt().mode().bits() as usize);
578                 }
579 
580                 return Err(SystemError::EBADF);
581             }
582             FcntlCommand::SetFlags => {
583                 // Set file status flags.
584                 let binding = ProcessManager::current_pcb().fd_table();
585                 let fd_table_guard = binding.write();
586 
587                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
588                     let arg = arg as u32;
589                     let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?;
590                     // drop guard 以避免无法调度的问题
591                     drop(fd_table_guard);
592                     file.lock_no_preempt().set_mode(mode)?;
593                     return Ok(0);
594                 }
595 
596                 return Err(SystemError::EBADF);
597             }
598             _ => {
599                 // TODO: unimplemented
600                 // 未实现的命令,返回0,不报错。
601 
602                 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
603                 return Ok(0);
604             }
605         }
606     }
607 
608     /// # ftruncate
609     ///
610     /// ## 描述
611     ///
612     /// 改变文件大小.
613     /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充.
614     /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小.
615     ///
616     /// ## 参数
617     ///
618     /// - `fd`:文件描述符
619     /// - `len`:文件大小
620     ///
621     /// ## 返回值
622     ///
623     /// 如果成功,返回0,否则返回错误码.
624     pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> {
625         let binding = ProcessManager::current_pcb().fd_table();
626         let fd_table_guard = binding.read();
627 
628         if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
629             // drop guard 以避免无法调度的问题
630             drop(fd_table_guard);
631             let r = file.lock_no_preempt().ftruncate(len).map(|_| 0);
632             return r;
633         }
634 
635         return Err(SystemError::EBADF);
636     }
637 
638     fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> {
639         let binding = ProcessManager::current_pcb().fd_table();
640         let fd_table_guard = binding.read();
641         let file = fd_table_guard
642             .get_file_by_fd(fd)
643             .ok_or(SystemError::EBADF)?;
644         // drop guard 以避免无法调度的问题
645         drop(fd_table_guard);
646 
647         let mut kstat = PosixKstat::new();
648         // 获取文件信息
649         let metadata = file.lock().metadata()?;
650         kstat.size = metadata.size as i64;
651         kstat.dev_id = metadata.dev_id as u64;
652         kstat.inode = metadata.inode_id as u64;
653         kstat.blcok_size = metadata.blk_size as i64;
654         kstat.blocks = metadata.blocks as u64;
655 
656         kstat.atime.tv_sec = metadata.atime.tv_sec;
657         kstat.atime.tv_nsec = metadata.atime.tv_nsec;
658         kstat.mtime.tv_sec = metadata.mtime.tv_sec;
659         kstat.mtime.tv_nsec = metadata.mtime.tv_nsec;
660         kstat.ctime.tv_sec = metadata.ctime.tv_sec;
661         kstat.ctime.tv_nsec = metadata.ctime.tv_nsec;
662 
663         kstat.nlink = metadata.nlinks as u64;
664         kstat.uid = metadata.uid as i32;
665         kstat.gid = metadata.gid as i32;
666         kstat.rdev = metadata.raw_dev as i64;
667         kstat.mode.bits = metadata.mode;
668         match file.lock().file_type() {
669             FileType::File => kstat.mode.insert(ModeType::S_IFMT),
670             FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
671             FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
672             FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
673             FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK),
674             FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK),
675             FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO),
676         }
677 
678         return Ok(kstat);
679     }
680 
681     pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
682         let kstat = Self::do_fstat(fd)?;
683         if usr_kstat.is_null() {
684             return Err(SystemError::EFAULT);
685         }
686         unsafe {
687             *usr_kstat = kstat;
688         }
689         return Ok(0);
690     }
691 }
692 #[repr(C)]
693 #[derive(Debug, Clone, Copy)]
694 pub struct IoVec {
695     /// 缓冲区的起始地址
696     pub iov_base: *mut u8,
697     /// 缓冲区的长度
698     pub iov_len: usize,
699 }
700 
701 /// 用于存储多个来自用户空间的IoVec
702 ///
703 /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
704 /// TODO:支持分散读写
705 #[derive(Debug)]
706 pub struct IoVecs(Vec<&'static mut [u8]>);
707 
708 impl IoVecs {
709     /// 从用户空间的IoVec中构造IoVecs
710     ///
711     /// @param iov 用户空间的IoVec
712     /// @param iovcnt 用户空间的IoVec的数量
713     /// @param readv 是否为readv系统调用
714     ///
715     /// @return 构造成功返回IoVecs,否则返回错误码
716     pub unsafe fn from_user(
717         iov: *const IoVec,
718         iovcnt: usize,
719         _readv: bool,
720     ) -> Result<Self, SystemError> {
721         // 检查iov指针所在空间是否合法
722         if !verify_area(
723             iov as usize as u64,
724             (iovcnt * core::mem::size_of::<IoVec>()) as u64,
725         ) {
726             return Err(SystemError::EFAULT);
727         }
728 
729         // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
730         let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
731 
732         let mut slices: Vec<&mut [u8]> = vec![];
733         slices.reserve(iovs.len());
734 
735         for iov in iovs.iter() {
736             if iov.iov_len == 0 {
737                 continue;
738             }
739 
740             if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) {
741                 return Err(SystemError::EFAULT);
742             }
743 
744             slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
745         }
746 
747         return Ok(Self(slices));
748     }
749 
750     /// @brief 将IoVecs中的数据聚合到一个缓冲区中
751     ///
752     /// @return 返回聚合后的缓冲区
753     pub fn gather(&self) -> Vec<u8> {
754         let mut buf = Vec::new();
755         for slice in self.0.iter() {
756             buf.extend_from_slice(slice);
757         }
758         return buf;
759     }
760 
761     /// @brief 将给定的数据分散写入到IoVecs中
762     pub fn scatter(&mut self, data: &[u8]) {
763         let mut data: &[u8] = data;
764         for slice in self.0.iter_mut() {
765             let len = core::cmp::min(slice.len(), data.len());
766             if len == 0 {
767                 continue;
768             }
769 
770             slice[..len].copy_from_slice(&data[..len]);
771             data = &data[len..];
772         }
773     }
774 
775     /// @brief 创建与IoVecs等长的缓冲区
776     ///
777     /// @param set_len 是否设置返回的Vec的len。
778     /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
779     /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
780     ///
781     /// @return 返回创建的缓冲区
782     pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
783         let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
784         let mut buf: Vec<u8> = Vec::with_capacity(total_len);
785 
786         if set_len {
787             unsafe {
788                 buf.set_len(total_len);
789             }
790         }
791         return buf;
792     }
793 }
794