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