xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision 1a72a751b18cf5bbe7b5b9e91aff530de0c18501)
1 use core::ffi::CStr;
2 
3 use alloc::{
4     string::{String, ToString},
5     sync::Arc,
6     vec::Vec,
7 };
8 
9 use crate::{
10     driver::base::{block::SeekFrom, device::DeviceNumber},
11     filesystem::vfs::file::FileDescriptorVec,
12     kerror,
13     libs::rwlock::RwLockWriteGuard,
14     mm::{verify_area, VirtAddr},
15     process::ProcessManager,
16     syscall::{
17         user_access::{check_and_clone_cstr, UserBufferReader, UserBufferWriter},
18         Syscall, SystemError,
19     },
20     time::TimeSpec,
21 };
22 
23 use super::{
24     core::{do_mkdir, do_remove_dir, do_unlink_at},
25     fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC},
26     file::{File, FileMode},
27     open::{do_faccessat, do_fchmodat, do_sys_open},
28     utils::{rsplit_path, user_path_at},
29     Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES,
30 };
31 // use crate::kdebug;
32 
33 pub const SEEK_SET: u32 = 0;
34 pub const SEEK_CUR: u32 = 1;
35 pub const SEEK_END: u32 = 2;
36 pub const SEEK_MAX: u32 = 3;
37 
38 bitflags! {
39     /// 文件类型和权限
40     #[repr(C)]
41     pub struct ModeType: u32 {
42         /// 掩码
43         const S_IFMT = 0o0_170_000;
44         /// 文件类型
45         const S_IFSOCK = 0o140000;
46         const S_IFLNK = 0o120000;
47         const S_IFREG = 0o100000;
48         const S_IFBLK = 0o060000;
49         const S_IFDIR = 0o040000;
50         const S_IFCHR = 0o020000;
51         const S_IFIFO = 0o010000;
52 
53         const S_ISUID = 0o004000;
54         const S_ISGID = 0o002000;
55         const S_ISVTX = 0o001000;
56         /// 文件用户权限
57         const S_IRWXU = 0o0700;
58         const S_IRUSR = 0o0400;
59         const S_IWUSR = 0o0200;
60         const S_IXUSR = 0o0100;
61         /// 文件组权限
62         const S_IRWXG = 0o0070;
63         const S_IRGRP = 0o0040;
64         const S_IWGRP = 0o0020;
65         const S_IXGRP = 0o0010;
66         /// 文件其他用户权限
67         const S_IRWXO = 0o0007;
68         const S_IROTH = 0o0004;
69         const S_IWOTH = 0o0002;
70         const S_IXOTH = 0o0001;
71 
72         /// 0o777
73         const S_IRWXUGO = Self::S_IRWXU.bits | Self::S_IRWXG.bits | Self::S_IRWXO.bits;
74         /// 0o7777
75         const S_IALLUGO = Self::S_ISUID.bits | Self::S_ISGID.bits | Self::S_ISVTX.bits| Self::S_IRWXUGO.bits;
76         /// 0o444
77         const S_IRUGO = Self::S_IRUSR.bits | Self::S_IRGRP.bits | Self::S_IROTH.bits;
78         /// 0o222
79         const S_IWUGO = Self::S_IWUSR.bits | Self::S_IWGRP.bits | Self::S_IWOTH.bits;
80         /// 0o111
81         const S_IXUGO = Self::S_IXUSR.bits | Self::S_IXGRP.bits | Self::S_IXOTH.bits;
82 
83 
84     }
85 }
86 
87 #[repr(C)]
88 /// # 文件信息结构体
89 pub struct PosixKstat {
90     /// 硬件设备ID
91     dev_id: u64,
92     /// inode号
93     inode: u64,
94     /// 硬链接数
95     nlink: u64,
96     /// 文件权限
97     mode: ModeType,
98     /// 所有者用户ID
99     uid: i32,
100     /// 所有者组ID
101     gid: i32,
102     /// 设备ID
103     rdev: i64,
104     /// 文件大小
105     size: i64,
106     /// 文件系统块大小
107     blcok_size: i64,
108     /// 分配的512B块数
109     blocks: u64,
110     /// 最后访问时间
111     atime: TimeSpec,
112     /// 最后修改时间
113     mtime: TimeSpec,
114     /// 最后状态变化时间
115     ctime: TimeSpec,
116     /// 用于填充结构体大小的空白数据
117     pub _pad: [i8; 24],
118 }
119 impl PosixKstat {
120     fn new() -> Self {
121         Self {
122             inode: 0,
123             dev_id: 0,
124             mode: ModeType { bits: 0 },
125             nlink: 0,
126             uid: 0,
127             gid: 0,
128             rdev: 0,
129             size: 0,
130             atime: TimeSpec {
131                 tv_sec: 0,
132                 tv_nsec: 0,
133             },
134             mtime: TimeSpec {
135                 tv_sec: 0,
136                 tv_nsec: 0,
137             },
138             ctime: TimeSpec {
139                 tv_sec: 0,
140                 tv_nsec: 0,
141             },
142             blcok_size: 0,
143             blocks: 0,
144             _pad: Default::default(),
145         }
146     }
147 }
148 
149 ///
150 ///  Arguments for how openat2(2) should open the target path. If only @flags and
151 ///  @mode are non-zero, then openat2(2) operates very similarly to openat(2).
152 ///
153 ///  However, unlike openat(2), unknown or invalid bits in @flags result in
154 ///  -EINVAL rather than being silently ignored. @mode must be zero unless one of
155 ///  {O_CREAT, O_TMPFILE} are set.
156 ///
157 /// ## 成员变量
158 ///
159 /// - flags: O_* flags.
160 /// - mode: O_CREAT/O_TMPFILE file mode.
161 /// - resolve: RESOLVE_* flags.
162 #[derive(Debug, Clone, Copy)]
163 #[repr(C)]
164 pub struct PosixOpenHow {
165     pub flags: u64,
166     pub mode: u64,
167     pub resolve: u64,
168 }
169 
170 impl PosixOpenHow {
171     #[allow(dead_code)]
172     pub fn new(flags: u64, mode: u64, resolve: u64) -> Self {
173         Self {
174             flags,
175             mode,
176             resolve,
177         }
178     }
179 }
180 
181 #[derive(Debug, Clone, Copy)]
182 pub struct OpenHow {
183     pub o_flags: FileMode,
184     pub mode: ModeType,
185     pub resolve: OpenHowResolve,
186 }
187 
188 impl OpenHow {
189     pub fn new(mut o_flags: FileMode, mut mode: ModeType, resolve: OpenHowResolve) -> Self {
190         if !o_flags.contains(FileMode::O_CREAT) {
191             mode = ModeType::empty();
192         }
193 
194         if o_flags.contains(FileMode::O_PATH) {
195             o_flags = o_flags.intersection(FileMode::O_PATH_FLAGS);
196         }
197 
198         Self {
199             o_flags,
200             mode,
201             resolve,
202         }
203     }
204 }
205 
206 impl From<PosixOpenHow> for OpenHow {
207     fn from(posix_open_how: PosixOpenHow) -> Self {
208         let o_flags = FileMode::from_bits_truncate(posix_open_how.flags as u32);
209         let mode = ModeType::from_bits_truncate(posix_open_how.mode as u32);
210         let resolve = OpenHowResolve::from_bits_truncate(posix_open_how.resolve as u64);
211         return Self::new(o_flags, mode, resolve);
212     }
213 }
214 
215 bitflags! {
216     pub struct OpenHowResolve: u64{
217         /// Block mount-point crossings
218         ///     (including bind-mounts).
219         const RESOLVE_NO_XDEV = 0x01;
220 
221         /// Block traversal through procfs-style
222         ///     "magic-links"
223         const RESOLVE_NO_MAGICLINKS = 0x02;
224 
225         /// Block traversal through all symlinks
226         ///     (implies OEXT_NO_MAGICLINKS)
227         const RESOLVE_NO_SYMLINKS = 0x04;
228         /// Block "lexical" trickery like
229         ///     "..", symlinks, and absolute
230         const RESOLVE_BENEATH = 0x08;
231         /// Make all jumps to "/" and ".."
232         ///     be scoped inside the dirfd
233         ///     (similar to chroot(2)).
234         const RESOLVE_IN_ROOT = 0x10;
235         // Only complete if resolution can be
236         // 			completed through cached lookup. May
237         // 			return -EAGAIN if that's not
238         // 			possible.
239         const RESOLVE_CACHED = 0x20;
240     }
241 }
242 impl Syscall {
243     /// @brief 为当前进程打开一个文件
244     ///
245     /// @param path 文件路径
246     /// @param o_flags 打开文件的标志位
247     ///
248     /// @return 文件描述符编号,或者是错误码
249     pub fn open(
250         path: &str,
251         flags: FileMode,
252         mode: ModeType,
253         follow_symlink: bool,
254     ) -> Result<usize, SystemError> {
255         return do_sys_open(AtFlags::AT_FDCWD.bits(), path, flags, mode, follow_symlink);
256     }
257 
258     pub fn openat(
259         dirfd: i32,
260         path: &str,
261         o_flags: FileMode,
262         mode: ModeType,
263         follow_symlink: bool,
264     ) -> Result<usize, SystemError> {
265         return do_sys_open(dirfd, path, o_flags, mode, follow_symlink);
266     }
267 
268     /// @brief 关闭文件
269     ///
270     /// @param fd 文件描述符编号
271     ///
272     /// @return 成功返回0,失败返回错误码
273     pub fn close(fd: usize) -> Result<usize, SystemError> {
274         let binding = ProcessManager::current_pcb().fd_table();
275         let mut fd_table_guard = binding.write();
276 
277         let res = fd_table_guard.drop_fd(fd as i32).map(|_| 0);
278 
279         return res;
280     }
281 
282     /// @brief 发送命令到文件描述符对应的设备,
283     ///
284     /// @param fd 文件描述符编号
285     /// @param cmd 设备相关的请求类型
286     ///
287     /// @return Ok(usize) 成功返回0
288     /// @return Err(SystemError) 读取失败,返回posix错误码
289     pub fn ioctl(fd: usize, cmd: u32, data: usize) -> Result<usize, SystemError> {
290         let binding = ProcessManager::current_pcb().fd_table();
291         let fd_table_guard = binding.read();
292 
293         let file = fd_table_guard
294             .get_file_by_fd(fd as i32)
295             .ok_or(SystemError::EBADF)?;
296 
297         // drop guard 以避免无法调度的问题
298         drop(fd_table_guard);
299         let r = file.lock_no_preempt().inode().ioctl(cmd, data);
300         return r;
301     }
302 
303     /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
304     ///
305     /// @param fd 文件描述符编号
306     /// @param buf 输出缓冲区。
307     ///
308     /// @return Ok(usize) 成功读取的数据的字节数
309     /// @return Err(SystemError) 读取失败,返回posix错误码
310     pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
311         let binding = ProcessManager::current_pcb().fd_table();
312         let fd_table_guard = binding.read();
313 
314         let file = fd_table_guard.get_file_by_fd(fd);
315         if file.is_none() {
316             return Err(SystemError::EBADF);
317         }
318         // drop guard 以避免无法调度的问题
319         drop(fd_table_guard);
320         let file = file.unwrap();
321 
322         return file.lock_no_preempt().read(buf.len(), buf);
323     }
324 
325     /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
326     ///
327     /// @param fd 文件描述符编号
328     /// @param buf 输入缓冲区。
329     ///
330     /// @return Ok(usize) 成功写入的数据的字节数
331     /// @return Err(SystemError) 写入失败,返回posix错误码
332     pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
333         let binding = ProcessManager::current_pcb().fd_table();
334         let fd_table_guard = binding.read();
335 
336         let file = fd_table_guard
337             .get_file_by_fd(fd)
338             .ok_or(SystemError::EBADF)?;
339 
340         // drop guard 以避免无法调度的问题
341         drop(fd_table_guard);
342         return file.lock_no_preempt().write(buf.len(), buf);
343     }
344 
345     /// @brief 调整文件操作指针的位置
346     ///
347     /// @param fd 文件描述符编号
348     /// @param seek 调整的方式
349     ///
350     /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
351     /// @return Err(SystemError) 调整失败,返回posix错误码
352     pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
353         let binding = ProcessManager::current_pcb().fd_table();
354         let fd_table_guard = binding.read();
355         let file = fd_table_guard
356             .get_file_by_fd(fd)
357             .ok_or(SystemError::EBADF)?;
358 
359         // drop guard 以避免无法调度的问题
360         drop(fd_table_guard);
361         return file.lock_no_preempt().lseek(seek);
362     }
363 
364     /// @brief 切换工作目录
365     ///
366     /// @param dest_path 目标路径
367     ///
368     /// @return   返回码  描述
369     ///      0       |          成功
370     ///
371     ///   EACCESS    |        权限不足
372     ///
373     ///    ELOOP     | 解析path时遇到路径循环
374     ///
375     /// ENAMETOOLONG |       路径名过长
376     ///
377     ///    ENOENT    |  目标文件或目录不存在
378     ///
379     ///    ENODIR    |  检索期间发现非目录项
380     ///
381     ///    ENOMEM    |      系统内存不足
382     ///
383     ///    EFAULT    |       错误的地址
384     ///
385     /// ENAMETOOLONG |        路径过长
386     pub fn chdir(dest_path: &str) -> Result<usize, SystemError> {
387         let proc = ProcessManager::current_pcb();
388         // Copy path to kernel space to avoid some security issues
389         let path = dest_path.to_string();
390         let mut new_path = String::from("");
391         if path.len() > 0 {
392             let cwd = match path.as_bytes()[0] {
393                 b'/' => String::from("/"),
394                 _ => proc.basic().cwd(),
395             };
396             let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect();
397             let path_split = path.split("/").filter(|&x| x != "");
398             for seg in path_split {
399                 if seg == ".." {
400                     cwd_vec.pop();
401                 } else if seg == "." {
402                     // 当前目录
403                 } else {
404                     cwd_vec.push(seg);
405                 }
406             }
407             //proc.basic().set_path(String::from(""));
408             for seg in cwd_vec {
409                 new_path.push_str("/");
410                 new_path.push_str(seg);
411             }
412             if new_path == "" {
413                 new_path = String::from("/");
414             }
415         }
416         let inode =
417             match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) {
418                 Err(e) => {
419                     kerror!("Change Directory Failed, Error = {:?}", e);
420                     return Err(SystemError::ENOENT);
421                 }
422                 Ok(i) => i,
423             };
424         let metadata = inode.metadata()?;
425         if metadata.file_type == FileType::Dir {
426             proc.basic_mut().set_cwd(String::from(new_path));
427             return Ok(0);
428         } else {
429             return Err(SystemError::ENOTDIR);
430         }
431     }
432 
433     /// @brief 获取当前进程的工作目录路径
434     ///
435     /// @param buf 指向缓冲区的指针
436     /// @param size 缓冲区的大小
437     ///
438     /// @return 成功,返回的指针指向包含工作目录路径的字符串
439     /// @return 错误,没有足够的空间
440     pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> {
441         let proc = ProcessManager::current_pcb();
442         let cwd = proc.basic().cwd();
443 
444         let cwd_bytes = cwd.as_bytes();
445         let cwd_len = cwd_bytes.len();
446         if cwd_len + 1 > buf.len() {
447             return Err(SystemError::ENOMEM);
448         }
449         buf[..cwd_len].copy_from_slice(cwd_bytes);
450         buf[cwd_len] = 0;
451 
452         return Ok(VirtAddr::new(buf.as_ptr() as usize));
453     }
454 
455     /// @brief 获取目录中的数据
456     ///
457     /// TODO: 这个函数的语义与Linux不一致,需要修改!!!
458     ///
459     /// @param fd 文件描述符号
460     /// @param buf 输出缓冲区
461     ///
462     /// @return 成功返回读取的字节数,失败返回错误码
463     pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
464         let dirent =
465             unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?;
466 
467         if fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD {
468             return Err(SystemError::EBADF);
469         }
470 
471         // 获取fd
472         let binding = ProcessManager::current_pcb().fd_table();
473         let fd_table_guard = binding.read();
474         let file = fd_table_guard
475             .get_file_by_fd(fd)
476             .ok_or(SystemError::EBADF)?;
477 
478         // drop guard 以避免无法调度的问题
479         drop(fd_table_guard);
480 
481         let res = file.lock_no_preempt().readdir(dirent).map(|x| x as usize);
482 
483         return res;
484     }
485 
486     /// @brief 创建文件夹
487     ///
488     /// @param path(r8) 路径 / mode(r9) 模式
489     ///
490     /// @return uint64_t 负数错误码 / 0表示成功
491     pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> {
492         return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
493     }
494 
495     /// **删除文件夹、取消文件的链接、删除文件的系统调用**
496     ///
497     /// ## 参数
498     ///
499     /// - `dirfd`:文件夹的文件描述符.目前暂未实现
500     /// - `pathname`:文件夹的路径
501     /// - `flags`:标志位
502     ///
503     ///
504     pub fn unlinkat(dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
505         let flags = AtFlags::from_bits(flags as i32).ok_or(SystemError::EINVAL)?;
506 
507         if flags.contains(AtFlags::AT_REMOVEDIR) {
508             // kdebug!("rmdir");
509             match do_remove_dir(dirfd, &pathname) {
510                 Err(err) => {
511                     kerror!("Failed to Remove Directory, Error Code = {:?}", err);
512                     return Err(err);
513                 }
514                 Ok(_) => {
515                     return Ok(0);
516                 }
517             }
518         }
519 
520         match do_unlink_at(dirfd, &pathname) {
521             Err(err) => {
522                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
523                 return Err(err);
524             }
525             Ok(_) => {
526                 return Ok(0);
527             }
528         }
529     }
530 
531     pub fn unlink(pathname: *const u8) -> Result<usize, SystemError> {
532         if pathname.is_null() {
533             return Err(SystemError::EFAULT);
534         }
535         let ureader = UserBufferReader::new(pathname, MAX_PATHLEN, true)?;
536 
537         let buf: &[u8] = ureader.buffer(0).unwrap();
538 
539         let pathname: &CStr = CStr::from_bytes_until_nul(buf).map_err(|_| SystemError::EINVAL)?;
540 
541         let pathname: &str = pathname.to_str().map_err(|_| SystemError::EINVAL)?;
542         if pathname.len() >= MAX_PATHLEN {
543             return Err(SystemError::ENAMETOOLONG);
544         }
545         let pathname = pathname.trim();
546 
547         return do_unlink_at(AtFlags::AT_FDCWD.bits(), pathname).map(|v| v as usize);
548     }
549 
550     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
551     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
552         let binding = ProcessManager::current_pcb().fd_table();
553         let mut fd_table_guard = binding.write();
554 
555         let old_file = fd_table_guard
556             .get_file_by_fd(oldfd)
557             .ok_or(SystemError::EBADF)?;
558 
559         let new_file = old_file
560             .lock_no_preempt()
561             .try_clone()
562             .ok_or(SystemError::EBADF)?;
563         // 申请文件描述符,并把文件对象存入其中
564         let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize);
565         return res;
566     }
567 
568     /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
569     /// 并返回新复制的文件结构体对应的fd.
570     /// 如果新fd已经打开,则会先关闭新fd.
571     ///
572     /// ## 参数
573     ///
574     /// - `oldfd`:旧文件描述符
575     /// - `newfd`:新文件描述符
576     ///
577     /// ## 返回值
578     ///
579     /// - 成功:新文件描述符
580     /// - 失败:错误码
581     pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> {
582         let binding = ProcessManager::current_pcb().fd_table();
583         let mut fd_table_guard = binding.write();
584         return Self::do_dup2(oldfd, newfd, &mut fd_table_guard);
585     }
586 
587     fn do_dup2(
588         oldfd: i32,
589         newfd: i32,
590         fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>,
591     ) -> Result<usize, SystemError> {
592         // 确认oldfd, newid是否有效
593         if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) {
594             return Err(SystemError::EBADF);
595         }
596 
597         if oldfd == newfd {
598             // 若oldfd与newfd相等
599             return Ok(newfd as usize);
600         }
601         let new_exists = fd_table_guard.get_file_by_fd(newfd).is_some();
602         if new_exists {
603             // close newfd
604             if let Err(_) = fd_table_guard.drop_fd(newfd) {
605                 // An I/O error occurred while attempting to close fildes2.
606                 return Err(SystemError::EIO);
607             }
608         }
609 
610         let old_file = fd_table_guard
611             .get_file_by_fd(oldfd)
612             .ok_or(SystemError::EBADF)?;
613         let new_file = old_file
614             .lock_no_preempt()
615             .try_clone()
616             .ok_or(SystemError::EBADF)?;
617         // 申请文件描述符,并把文件对象存入其中
618         let res = fd_table_guard
619             .alloc_fd(new_file, Some(newfd))
620             .map(|x| x as usize);
621         return res;
622     }
623 
624     /// # fcntl
625     ///
626     /// ## 参数
627     ///
628     /// - `fd`:文件描述符
629     /// - `cmd`:命令
630     /// - `arg`:参数
631     pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> {
632         match cmd {
633             FcntlCommand::DupFd => {
634                 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
635                     return Err(SystemError::EBADF);
636                 }
637                 let arg = arg as usize;
638                 for i in arg..FileDescriptorVec::PROCESS_MAX_FD {
639                     let binding = ProcessManager::current_pcb().fd_table();
640                     let mut fd_table_guard = binding.write();
641                     if fd_table_guard.get_file_by_fd(fd).is_none() {
642                         return Self::do_dup2(fd, i as i32, &mut fd_table_guard);
643                     }
644                 }
645                 return Err(SystemError::EMFILE);
646             }
647             FcntlCommand::GetFd => {
648                 // Get file descriptor flags.
649                 let binding = ProcessManager::current_pcb().fd_table();
650                 let fd_table_guard = binding.read();
651                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
652                     // drop guard 以避免无法调度的问题
653                     drop(fd_table_guard);
654 
655                     if file.lock().close_on_exec() {
656                         return Ok(FD_CLOEXEC as usize);
657                     }
658                 }
659                 return Err(SystemError::EBADF);
660             }
661             FcntlCommand::SetFd => {
662                 // Set file descriptor flags.
663                 let binding = ProcessManager::current_pcb().fd_table();
664                 let fd_table_guard = binding.write();
665 
666                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
667                     // drop guard 以避免无法调度的问题
668                     drop(fd_table_guard);
669                     let arg = arg as u32;
670                     if arg & FD_CLOEXEC != 0 {
671                         file.lock().set_close_on_exec(true);
672                     } else {
673                         file.lock().set_close_on_exec(false);
674                     }
675                     return Ok(0);
676                 }
677                 return Err(SystemError::EBADF);
678             }
679 
680             FcntlCommand::GetFlags => {
681                 // Get file status flags.
682                 let binding = ProcessManager::current_pcb().fd_table();
683                 let fd_table_guard = binding.read();
684 
685                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
686                     // drop guard 以避免无法调度的问题
687                     drop(fd_table_guard);
688                     return Ok(file.lock_no_preempt().mode().bits() as usize);
689                 }
690 
691                 return Err(SystemError::EBADF);
692             }
693             FcntlCommand::SetFlags => {
694                 // Set file status flags.
695                 let binding = ProcessManager::current_pcb().fd_table();
696                 let fd_table_guard = binding.write();
697 
698                 if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
699                     let arg = arg as u32;
700                     let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?;
701                     // drop guard 以避免无法调度的问题
702                     drop(fd_table_guard);
703                     file.lock_no_preempt().set_mode(mode)?;
704                     return Ok(0);
705                 }
706 
707                 return Err(SystemError::EBADF);
708             }
709             _ => {
710                 // TODO: unimplemented
711                 // 未实现的命令,返回0,不报错。
712 
713                 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
714                 return Ok(0);
715             }
716         }
717     }
718 
719     /// # ftruncate
720     ///
721     /// ## 描述
722     ///
723     /// 改变文件大小.
724     /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充.
725     /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小.
726     ///
727     /// ## 参数
728     ///
729     /// - `fd`:文件描述符
730     /// - `len`:文件大小
731     ///
732     /// ## 返回值
733     ///
734     /// 如果成功,返回0,否则返回错误码.
735     pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> {
736         let binding = ProcessManager::current_pcb().fd_table();
737         let fd_table_guard = binding.read();
738 
739         if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
740             // drop guard 以避免无法调度的问题
741             drop(fd_table_guard);
742             let r = file.lock_no_preempt().ftruncate(len).map(|_| 0);
743             return r;
744         }
745 
746         return Err(SystemError::EBADF);
747     }
748 
749     fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> {
750         let binding = ProcessManager::current_pcb().fd_table();
751         let fd_table_guard = binding.read();
752         let file = fd_table_guard
753             .get_file_by_fd(fd)
754             .ok_or(SystemError::EBADF)?;
755         // drop guard 以避免无法调度的问题
756         drop(fd_table_guard);
757 
758         let mut kstat = PosixKstat::new();
759         // 获取文件信息
760         let metadata = file.lock().metadata()?;
761         kstat.size = metadata.size as i64;
762         kstat.dev_id = metadata.dev_id as u64;
763         kstat.inode = metadata.inode_id.into() as u64;
764         kstat.blcok_size = metadata.blk_size as i64;
765         kstat.blocks = metadata.blocks as u64;
766 
767         kstat.atime.tv_sec = metadata.atime.tv_sec;
768         kstat.atime.tv_nsec = metadata.atime.tv_nsec;
769         kstat.mtime.tv_sec = metadata.mtime.tv_sec;
770         kstat.mtime.tv_nsec = metadata.mtime.tv_nsec;
771         kstat.ctime.tv_sec = metadata.ctime.tv_sec;
772         kstat.ctime.tv_nsec = metadata.ctime.tv_nsec;
773 
774         kstat.nlink = metadata.nlinks as u64;
775         kstat.uid = metadata.uid as i32;
776         kstat.gid = metadata.gid as i32;
777         kstat.rdev = metadata.raw_dev as i64;
778         kstat.mode = metadata.mode;
779         match file.lock().file_type() {
780             FileType::File => kstat.mode.insert(ModeType::S_IFREG),
781             FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR),
782             FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK),
783             FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR),
784             FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK),
785             FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK),
786             FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO),
787             FileType::KvmDevice => kstat.mode.insert(ModeType::S_IFCHR),
788         }
789 
790         return Ok(kstat);
791     }
792 
793     pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
794         let kstat = Self::do_fstat(fd)?;
795         if usr_kstat.is_null() {
796             return Err(SystemError::EFAULT);
797         }
798         unsafe {
799             *usr_kstat = kstat;
800         }
801         return Ok(0);
802     }
803 
804     pub fn stat(path: &str, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
805         let fd = Self::open(path, FileMode::O_RDONLY, ModeType::empty(), true)?;
806         let r = Self::fstat(fd as i32, user_kstat);
807         Self::close(fd).ok();
808         return r;
809     }
810 
811     pub fn lstat(path: &str, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> {
812         let fd = Self::open(path, FileMode::O_RDONLY, ModeType::empty(), false)?;
813         let r = Self::fstat(fd as i32, user_kstat);
814         Self::close(fd).ok();
815         return r;
816     }
817 
818     pub fn mknod(
819         path_ptr: *const i8,
820         mode: ModeType,
821         dev_t: DeviceNumber,
822     ) -> Result<usize, SystemError> {
823         // 安全检验
824         let len = unsafe { CStr::from_ptr(path_ptr).to_bytes().len() };
825         let user_buffer = UserBufferReader::new(path_ptr, len, true)?;
826         let buf = user_buffer.read_from_user::<u8>(0)?;
827         let path = core::str::from_utf8(buf).map_err(|_| SystemError::EINVAL)?;
828 
829         // 文件名过长
830         if path.len() > MAX_PATHLEN as usize {
831             return Err(SystemError::ENAMETOOLONG);
832         }
833 
834         let inode: Result<Arc<dyn IndexNode>, SystemError> =
835             ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES);
836 
837         if inode.is_ok() {
838             return Err(SystemError::EEXIST);
839         }
840 
841         let (filename, parent_path) = rsplit_path(path);
842 
843         // 查找父目录
844         let parent_inode: Arc<dyn IndexNode> = ROOT_INODE()
845             .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?;
846         // 创建nod
847         parent_inode.mknod(filename, mode, dev_t)?;
848 
849         return Ok(0);
850     }
851 
852     pub fn writev(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> {
853         // IoVecs会进行用户态检验
854         let iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, false) }?;
855 
856         let data = iovecs.gather();
857 
858         Self::write(fd, &data)
859     }
860 
861     pub fn readv(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> {
862         // IoVecs会进行用户态检验
863         let mut iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, true) }?;
864 
865         let mut data = Vec::new();
866         data.resize(iovecs.0.iter().map(|x| x.len()).sum(), 0);
867 
868         let len = Self::read(fd, &mut data)?;
869 
870         iovecs.scatter(&data[..len]);
871 
872         return Ok(len);
873     }
874 
875     pub fn readlink_at(
876         dirfd: i32,
877         path: *const u8,
878         user_buf: *mut u8,
879         buf_size: usize,
880     ) -> Result<usize, SystemError> {
881         let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?;
882         let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?;
883 
884         if path.len() == 0 {
885             return Err(SystemError::EINVAL);
886         }
887 
888         let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?;
889 
890         let inode = inode.lookup(path.as_str())?;
891         if inode.metadata()?.file_type != FileType::SymLink {
892             return Err(SystemError::EINVAL);
893         }
894 
895         let ubuf = user_buf.buffer::<u8>(0).unwrap();
896 
897         let mut file = File::new(inode, FileMode::O_RDONLY)?;
898 
899         let len = file.read(buf_size, ubuf)?;
900 
901         return Ok(len);
902     }
903 
904     pub fn readlink(
905         path: *const u8,
906         user_buf: *mut u8,
907         buf_size: usize,
908     ) -> Result<usize, SystemError> {
909         return Self::readlink_at(AtFlags::AT_FDCWD.bits(), path, user_buf, buf_size);
910     }
911 
912     pub fn access(pathname: *const u8, mode: u32) -> Result<usize, SystemError> {
913         return do_faccessat(
914             AtFlags::AT_FDCWD.bits(),
915             pathname,
916             ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
917             0,
918         );
919     }
920 
921     pub fn faccessat2(
922         dirfd: i32,
923         pathname: *const u8,
924         mode: u32,
925         flags: u32,
926     ) -> Result<usize, SystemError> {
927         return do_faccessat(
928             dirfd,
929             pathname,
930             ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
931             flags,
932         );
933     }
934 
935     pub fn chmod(pathname: *const u8, mode: u32) -> Result<usize, SystemError> {
936         return do_fchmodat(
937             AtFlags::AT_FDCWD.bits(),
938             pathname,
939             ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
940         );
941     }
942 
943     pub fn fchmodat(dirfd: i32, pathname: *const u8, mode: u32) -> Result<usize, SystemError> {
944         return do_fchmodat(
945             dirfd,
946             pathname,
947             ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?,
948         );
949     }
950 
951     pub fn fchmod(fd: i32, mode: u32) -> Result<usize, SystemError> {
952         let _mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?;
953         let binding = ProcessManager::current_pcb().fd_table();
954         let fd_table_guard = binding.read();
955         let _file = fd_table_guard
956             .get_file_by_fd(fd)
957             .ok_or(SystemError::EBADF)?;
958 
959         // fchmod没完全实现,因此不修改文件的权限
960         // todo: 实现fchmod
961         kwarn!("fchmod not fully implemented");
962         return Ok(0);
963     }
964 }
965 
966 #[repr(C)]
967 #[derive(Debug, Clone, Copy)]
968 pub struct IoVec {
969     /// 缓冲区的起始地址
970     pub iov_base: *mut u8,
971     /// 缓冲区的长度
972     pub iov_len: usize,
973 }
974 
975 /// 用于存储多个来自用户空间的IoVec
976 ///
977 /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
978 /// TODO:支持分散读写
979 #[derive(Debug)]
980 pub struct IoVecs(Vec<&'static mut [u8]>);
981 
982 impl IoVecs {
983     /// 从用户空间的IoVec中构造IoVecs
984     ///
985     /// @param iov 用户空间的IoVec
986     /// @param iovcnt 用户空间的IoVec的数量
987     /// @param readv 是否为readv系统调用
988     ///
989     /// @return 构造成功返回IoVecs,否则返回错误码
990     pub unsafe fn from_user(
991         iov: *const IoVec,
992         iovcnt: usize,
993         _readv: bool,
994     ) -> Result<Self, SystemError> {
995         // 检查iov指针所在空间是否合法
996         verify_area(
997             VirtAddr::new(iov as usize),
998             iovcnt * core::mem::size_of::<IoVec>(),
999         )
1000         .map_err(|_| SystemError::EFAULT)?;
1001 
1002         // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
1003         let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
1004 
1005         let mut slices: Vec<&mut [u8]> = vec![];
1006         slices.reserve(iovs.len());
1007 
1008         for iov in iovs.iter() {
1009             if iov.iov_len == 0 {
1010                 continue;
1011             }
1012 
1013             verify_area(
1014                 VirtAddr::new(iov.iov_base as usize),
1015                 iovcnt * core::mem::size_of::<IoVec>(),
1016             )
1017             .map_err(|_| SystemError::EFAULT)?;
1018 
1019             slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
1020         }
1021 
1022         return Ok(Self(slices));
1023     }
1024 
1025     /// @brief 将IoVecs中的数据聚合到一个缓冲区中
1026     ///
1027     /// @return 返回聚合后的缓冲区
1028     pub fn gather(&self) -> Vec<u8> {
1029         let mut buf = Vec::new();
1030         for slice in self.0.iter() {
1031             buf.extend_from_slice(slice);
1032         }
1033         return buf;
1034     }
1035 
1036     /// @brief 将给定的数据分散写入到IoVecs中
1037     pub fn scatter(&mut self, data: &[u8]) {
1038         let mut data: &[u8] = data;
1039         for slice in self.0.iter_mut() {
1040             let len = core::cmp::min(slice.len(), data.len());
1041             if len == 0 {
1042                 continue;
1043             }
1044 
1045             slice[..len].copy_from_slice(&data[..len]);
1046             data = &data[len..];
1047         }
1048     }
1049 
1050     /// @brief 创建与IoVecs等长的缓冲区
1051     ///
1052     /// @param set_len 是否设置返回的Vec的len。
1053     /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
1054     /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
1055     ///
1056     /// @return 返回创建的缓冲区
1057     pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
1058         let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
1059         let mut buf: Vec<u8> = Vec::with_capacity(total_len);
1060 
1061         if set_len {
1062             buf.resize(total_len, 0);
1063         }
1064         return buf;
1065     }
1066 }
1067