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