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