xref: /DragonOS/kernel/src/filesystem/vfs/syscall.rs (revision ab5c8ca46db8e7d4793a9791292122b0b9684274)
1004e86ffSlogin 
2*ab5c8ca4Slogin use alloc::{boxed::Box, sync::Arc, vec::Vec};
3004e86ffSlogin 
4004e86ffSlogin use crate::{
5*ab5c8ca4Slogin     arch::asm::{current::current_pcb},
62b771e32SGou Ngai     filesystem::vfs::file::FileDescriptorVec,
7004e86ffSlogin     include::bindings::bindings::{
8*ab5c8ca4Slogin         verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM,
9004e86ffSlogin     },
10004e86ffSlogin     io::SeekFrom,
112b771e32SGou Ngai     kerror,
12*ab5c8ca4Slogin     syscall::{Syscall, SystemError},
13004e86ffSlogin };
14004e86ffSlogin 
15004e86ffSlogin use super::{
16*ab5c8ca4Slogin     core::{do_mkdir, do_remove_dir, do_unlink_at},
17004e86ffSlogin     file::{File, FileMode},
18*ab5c8ca4Slogin     utils::rsplit_path,
19*ab5c8ca4Slogin     Dirent, FileType, IndexNode, ROOT_INODE,
20004e86ffSlogin };
21004e86ffSlogin 
22*ab5c8ca4Slogin pub const SEEK_SET: u32 = 0;
23*ab5c8ca4Slogin pub const SEEK_CUR: u32 = 1;
24*ab5c8ca4Slogin pub const SEEK_END: u32 = 2;
25*ab5c8ca4Slogin pub const SEEK_MAX: u32 = 3;
26004e86ffSlogin 
27*ab5c8ca4Slogin impl Syscall {
28*ab5c8ca4Slogin     /// @brief 为当前进程打开一个文件
29*ab5c8ca4Slogin     ///
30*ab5c8ca4Slogin     /// @param path 文件路径
31*ab5c8ca4Slogin     /// @param o_flags 打开文件的标志位
32*ab5c8ca4Slogin     ///
33*ab5c8ca4Slogin     /// @return 文件描述符编号,或者是错误码
34*ab5c8ca4Slogin     pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> {
35*ab5c8ca4Slogin         // 文件名过长
36*ab5c8ca4Slogin         if path.len() > PAGE_4K_SIZE as usize {
37*ab5c8ca4Slogin             return Err(SystemError::ENAMETOOLONG);
38*ab5c8ca4Slogin         }
39*ab5c8ca4Slogin 
40*ab5c8ca4Slogin         let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path);
41*ab5c8ca4Slogin 
42*ab5c8ca4Slogin         let inode: Arc<dyn IndexNode> = if inode.is_err() {
43*ab5c8ca4Slogin             let errno = inode.unwrap_err();
44*ab5c8ca4Slogin             // 文件不存在,且需要创建
45*ab5c8ca4Slogin             if mode.contains(FileMode::O_CREAT)
46*ab5c8ca4Slogin                 && !mode.contains(FileMode::O_DIRECTORY)
47*ab5c8ca4Slogin                 && errno == SystemError::ENOENT
48*ab5c8ca4Slogin             {
49*ab5c8ca4Slogin                 let (filename, parent_path) = rsplit_path(path);
50*ab5c8ca4Slogin                 // 查找父目录
51*ab5c8ca4Slogin                 let parent_inode: Arc<dyn IndexNode> =
52*ab5c8ca4Slogin                     ROOT_INODE().lookup(parent_path.unwrap_or("/"))?;
53*ab5c8ca4Slogin                 // 创建文件
54*ab5c8ca4Slogin                 let inode: Arc<dyn IndexNode> =
55*ab5c8ca4Slogin                     parent_inode.create(filename, FileType::File, 0o777)?;
56*ab5c8ca4Slogin                 inode
57004e86ffSlogin             } else {
58*ab5c8ca4Slogin                 // 不需要创建文件,因此返回错误码
59*ab5c8ca4Slogin                 return Err(errno);
60004e86ffSlogin             }
61004e86ffSlogin         } else {
62*ab5c8ca4Slogin             inode.unwrap()
63004e86ffSlogin         };
64004e86ffSlogin 
65*ab5c8ca4Slogin         let file_type: FileType = inode.metadata()?.file_type;
66*ab5c8ca4Slogin         // 如果要打开的是文件夹,而目标不是文件夹
67*ab5c8ca4Slogin         if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir {
68*ab5c8ca4Slogin             return Err(SystemError::ENOTDIR);
69004e86ffSlogin         }
70*ab5c8ca4Slogin 
71*ab5c8ca4Slogin         // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件
72*ab5c8ca4Slogin         if mode.contains(FileMode::O_TRUNC)
73*ab5c8ca4Slogin             && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY))
74*ab5c8ca4Slogin             && file_type == FileType::File
75*ab5c8ca4Slogin         {
76*ab5c8ca4Slogin             inode.truncate(0)?;
77*ab5c8ca4Slogin         }
78*ab5c8ca4Slogin 
79*ab5c8ca4Slogin         // 创建文件对象
80*ab5c8ca4Slogin         let mut file: File = File::new(inode, mode)?;
81*ab5c8ca4Slogin 
82*ab5c8ca4Slogin         // 打开模式为“追加”
83*ab5c8ca4Slogin         if mode.contains(FileMode::O_APPEND) {
84*ab5c8ca4Slogin             file.lseek(SeekFrom::SeekEnd(0))?;
85*ab5c8ca4Slogin         }
86*ab5c8ca4Slogin 
87*ab5c8ca4Slogin         // 把文件对象存入pcb
88*ab5c8ca4Slogin         return current_pcb().alloc_fd(file, None).map(|fd| fd as usize);
89*ab5c8ca4Slogin     }
90*ab5c8ca4Slogin 
91*ab5c8ca4Slogin     /// @brief 关闭文件
92*ab5c8ca4Slogin     ///
93*ab5c8ca4Slogin     /// @param fd 文件描述符编号
94*ab5c8ca4Slogin     ///
95*ab5c8ca4Slogin     /// @return 成功返回0,失败返回错误码
96*ab5c8ca4Slogin     pub fn close(fd: usize) -> Result<usize, SystemError> {
97*ab5c8ca4Slogin         return current_pcb().drop_fd(fd as i32).map(|_| 0);
98*ab5c8ca4Slogin     }
99*ab5c8ca4Slogin 
100*ab5c8ca4Slogin     /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。
101*ab5c8ca4Slogin     ///
102*ab5c8ca4Slogin     /// @param fd 文件描述符编号
103*ab5c8ca4Slogin     /// @param buf 输出缓冲区。
104*ab5c8ca4Slogin     ///
105*ab5c8ca4Slogin     /// @return Ok(usize) 成功读取的数据的字节数
106*ab5c8ca4Slogin     /// @return Err(SystemError) 读取失败,返回posix错误码
107*ab5c8ca4Slogin     pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
108*ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
109*ab5c8ca4Slogin         if file.is_none() {
110*ab5c8ca4Slogin             return Err(SystemError::EBADF);
111*ab5c8ca4Slogin         }
112*ab5c8ca4Slogin         let file: &mut File = file.unwrap();
113*ab5c8ca4Slogin 
114*ab5c8ca4Slogin         return file.read(buf.len(), buf);
115*ab5c8ca4Slogin     }
116*ab5c8ca4Slogin 
117*ab5c8ca4Slogin     /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。
118*ab5c8ca4Slogin     ///
119*ab5c8ca4Slogin     /// @param fd 文件描述符编号
120*ab5c8ca4Slogin     /// @param buf 输入缓冲区。
121*ab5c8ca4Slogin     ///
122*ab5c8ca4Slogin     /// @return Ok(usize) 成功写入的数据的字节数
123*ab5c8ca4Slogin     /// @return Err(SystemError) 写入失败,返回posix错误码
124*ab5c8ca4Slogin     pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> {
125*ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
126*ab5c8ca4Slogin         if file.is_none() {
127*ab5c8ca4Slogin             return Err(SystemError::EBADF);
128*ab5c8ca4Slogin         }
129*ab5c8ca4Slogin         let file: &mut File = file.unwrap();
130*ab5c8ca4Slogin 
131*ab5c8ca4Slogin         return file.write(buf.len(), buf);
132*ab5c8ca4Slogin     }
133*ab5c8ca4Slogin 
134*ab5c8ca4Slogin     /// @brief 调整文件操作指针的位置
135*ab5c8ca4Slogin     ///
136*ab5c8ca4Slogin     /// @param fd 文件描述符编号
137*ab5c8ca4Slogin     /// @param seek 调整的方式
138*ab5c8ca4Slogin     ///
139*ab5c8ca4Slogin     /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量
140*ab5c8ca4Slogin     /// @return Err(SystemError) 调整失败,返回posix错误码
141*ab5c8ca4Slogin     pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> {
142*ab5c8ca4Slogin         let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd);
143*ab5c8ca4Slogin         if file.is_none() {
144*ab5c8ca4Slogin             return Err(SystemError::EBADF);
145*ab5c8ca4Slogin         }
146*ab5c8ca4Slogin         let file: &mut File = file.unwrap();
147*ab5c8ca4Slogin         return file.lseek(seek);
148004e86ffSlogin     }
149004e86ffSlogin 
150004e86ffSlogin     /// @brief 切换工作目录
151004e86ffSlogin     ///
152004e86ffSlogin     /// @param dest_path 目标路径
153004e86ffSlogin     ///
154004e86ffSlogin     /// @return   返回码  描述
155004e86ffSlogin     ///      0       |          成功
156004e86ffSlogin     ///
157004e86ffSlogin     ///   EACCESS    |        权限不足
158004e86ffSlogin     ///
159004e86ffSlogin     ///    ELOOP     | 解析path时遇到路径循环
160004e86ffSlogin     ///
161004e86ffSlogin     /// ENAMETOOLONG |       路径名过长
162004e86ffSlogin     ///
163004e86ffSlogin     ///    ENOENT    |  目标文件或目录不存在
164004e86ffSlogin     ///
165004e86ffSlogin     ///    ENODIR    |  检索期间发现非目录项
166004e86ffSlogin     ///
167004e86ffSlogin     ///    ENOMEM    |      系统内存不足
168004e86ffSlogin     ///
169004e86ffSlogin     ///    EFAULT    |       错误的地址
170004e86ffSlogin     ///
171004e86ffSlogin     /// ENAMETOOLONG |        路径过长
172*ab5c8ca4Slogin     pub fn chdir(dest_path: &str) -> Result<usize, SystemError> {
173*ab5c8ca4Slogin         // Copy path to kernel space to avoid some security issues
174*ab5c8ca4Slogin         let path: Box<&str> = Box::new(dest_path);
175004e86ffSlogin         let inode = match ROOT_INODE().lookup(&path) {
176004e86ffSlogin             Err(e) => {
177676b8ef6SMork                 kerror!("Change Directory Failed, Error = {:?}", e);
178*ab5c8ca4Slogin                 return Err(SystemError::ENOENT);
179004e86ffSlogin             }
180004e86ffSlogin             Ok(i) => i,
181004e86ffSlogin         };
182004e86ffSlogin 
183004e86ffSlogin         match inode.metadata() {
184004e86ffSlogin             Err(e) => {
185676b8ef6SMork                 kerror!("INode Get MetaData Failed, Error = {:?}", e);
186*ab5c8ca4Slogin                 return Err(SystemError::ENOENT);
187004e86ffSlogin             }
188004e86ffSlogin             Ok(i) => {
189004e86ffSlogin                 if let FileType::Dir = i.file_type {
190*ab5c8ca4Slogin                     return Ok(0);
191004e86ffSlogin                 } else {
192*ab5c8ca4Slogin                     return Err(SystemError::ENOTDIR);
193004e86ffSlogin                 }
194004e86ffSlogin             }
195004e86ffSlogin         }
196004e86ffSlogin     }
197004e86ffSlogin 
198004e86ffSlogin     /// @brief 获取目录中的数据
199004e86ffSlogin     ///
200*ab5c8ca4Slogin     /// TODO: 这个函数的语义与Linux不一致,需要修改!!!
201*ab5c8ca4Slogin     ///
202004e86ffSlogin     /// @param fd 文件描述符号
203*ab5c8ca4Slogin     /// @param buf 输出缓冲区
204*ab5c8ca4Slogin     ///
205*ab5c8ca4Slogin     /// @return 成功返回读取的字节数,失败返回错误码
206*ab5c8ca4Slogin     pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> {
207*ab5c8ca4Slogin         let dirent =
208*ab5c8ca4Slogin             unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?;
209004e86ffSlogin 
210004e86ffSlogin         if fd < 0 || fd as u32 > PROC_MAX_FD_NUM {
211*ab5c8ca4Slogin             return Err(SystemError::EBADF);
212004e86ffSlogin         }
213004e86ffSlogin 
214004e86ffSlogin         // 获取fd
215004e86ffSlogin         let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) {
216004e86ffSlogin             None => {
217*ab5c8ca4Slogin                 return Err(SystemError::EBADF);
218004e86ffSlogin             }
219004e86ffSlogin             Some(file) => file,
220004e86ffSlogin         };
221004e86ffSlogin         // kdebug!("file={file:?}");
222004e86ffSlogin 
223*ab5c8ca4Slogin         return file.readdir(dirent).map(|x| x as usize);
224004e86ffSlogin     }
225004e86ffSlogin 
226004e86ffSlogin     /// @brief 创建文件夹
227004e86ffSlogin     ///
228004e86ffSlogin     /// @param path(r8) 路径 / mode(r9) 模式
229004e86ffSlogin     ///
230004e86ffSlogin     /// @return uint64_t 负数错误码 / 0表示成功
231*ab5c8ca4Slogin     pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> {
232*ab5c8ca4Slogin         return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize);
233004e86ffSlogin     }
234004e86ffSlogin 
235*ab5c8ca4Slogin     /// **删除文件夹、取消文件的链接、删除文件的系统调用**
236004e86ffSlogin     ///
237*ab5c8ca4Slogin     /// ## 参数
238004e86ffSlogin     ///
239*ab5c8ca4Slogin     /// - `dirfd`:文件夹的文件描述符.目前暂未实现
240*ab5c8ca4Slogin     /// - `pathname`:文件夹的路径
241*ab5c8ca4Slogin     /// - `flags`:标志位
242004e86ffSlogin     ///
243004e86ffSlogin     ///
244*ab5c8ca4Slogin     pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> {
245004e86ffSlogin         // kdebug!("sys_unlink_at={path:?}");
246*ab5c8ca4Slogin         if (flags & (!AT_REMOVEDIR)) != 0 {
247*ab5c8ca4Slogin             return Err(SystemError::EINVAL);
248004e86ffSlogin         }
249004e86ffSlogin 
250*ab5c8ca4Slogin         if (flags & AT_REMOVEDIR) > 0 {
251004e86ffSlogin             // kdebug!("rmdir");
252*ab5c8ca4Slogin             match do_remove_dir(&pathname) {
253004e86ffSlogin                 Err(err) => {
254676b8ef6SMork                     kerror!("Failed to Remove Directory, Error Code = {:?}", err);
255*ab5c8ca4Slogin                     return Err(err);
256004e86ffSlogin                 }
257004e86ffSlogin                 Ok(_) => {
258*ab5c8ca4Slogin                     return Ok(0);
259004e86ffSlogin                 }
260004e86ffSlogin             }
261004e86ffSlogin         }
262004e86ffSlogin 
263*ab5c8ca4Slogin         match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) {
264004e86ffSlogin             Err(err) => {
265676b8ef6SMork                 kerror!("Failed to Remove Directory, Error Code = {:?}", err);
266*ab5c8ca4Slogin                 return Err(err);
267004e86ffSlogin             }
268004e86ffSlogin             Ok(_) => {
269*ab5c8ca4Slogin                 return Ok(0);
270004e86ffSlogin             }
271004e86ffSlogin         }
272004e86ffSlogin     }
2732b771e32SGou Ngai 
274*ab5c8ca4Slogin     /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd
275*ab5c8ca4Slogin     pub fn dup(oldfd: i32) -> Result<usize, SystemError> {
2762b771e32SGou Ngai         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
2772b771e32SGou Ngai             // 获得当前文件描述符数组
2782b771e32SGou Ngai             // 确认oldfd是否有效
2792b771e32SGou Ngai             if FileDescriptorVec::validate_fd(oldfd) {
2802b771e32SGou Ngai                 if let Some(file) = &fds.fds[oldfd as usize] {
2812b771e32SGou Ngai                     // 尝试获取对应的文件结构体
282*ab5c8ca4Slogin                     let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?;
283*ab5c8ca4Slogin 
2842b771e32SGou Ngai                     // 申请文件描述符,并把文件对象存入其中
285*ab5c8ca4Slogin                     let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize);
2862b771e32SGou Ngai                     return res;
2872b771e32SGou Ngai                 }
2882b771e32SGou Ngai                 // oldfd对应的文件不存在
2892b771e32SGou Ngai                 return Err(SystemError::EBADF);
2902b771e32SGou Ngai             }
2912b771e32SGou Ngai             return Err(SystemError::EBADF);
2922b771e32SGou Ngai         } else {
2932b771e32SGou Ngai             return Err(SystemError::EMFILE);
2942b771e32SGou Ngai         }
2952b771e32SGou Ngai     }
2962b771e32SGou Ngai 
297*ab5c8ca4Slogin     /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体,
298*ab5c8ca4Slogin     /// 并返回新复制的文件结构体对应的fd.
299*ab5c8ca4Slogin     /// 如果新fd已经打开,则会先关闭新fd.
300*ab5c8ca4Slogin     ///
301*ab5c8ca4Slogin     /// ## 参数
302*ab5c8ca4Slogin     ///
303*ab5c8ca4Slogin     /// - `oldfd`:旧文件描述符
304*ab5c8ca4Slogin     /// - `newfd`:新文件描述符
305*ab5c8ca4Slogin     ///
306*ab5c8ca4Slogin     /// ## 返回值
307*ab5c8ca4Slogin     ///
308*ab5c8ca4Slogin     /// - 成功:新文件描述符
309*ab5c8ca4Slogin     /// - 失败:错误码
310*ab5c8ca4Slogin     pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> {
3112b771e32SGou Ngai         if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) {
3122b771e32SGou Ngai             // 获得当前文件描述符数组
3132b771e32SGou Ngai             if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) {
3142b771e32SGou Ngai                 //确认oldfd, newid是否有效
3152b771e32SGou Ngai                 if oldfd == newfd {
3162b771e32SGou Ngai                     // 若oldfd与newfd相等
317*ab5c8ca4Slogin                     return Ok(newfd as usize);
3182b771e32SGou Ngai                 }
3192b771e32SGou Ngai 
3202b771e32SGou Ngai                 if let Some(file) = &fds.fds[oldfd as usize] {
3212b771e32SGou Ngai                     if fds.fds[newfd as usize].is_some() {
3222b771e32SGou Ngai                         // close newfd
3232b771e32SGou Ngai                         if let Err(_) = current_pcb().drop_fd(newfd) {
3242b771e32SGou Ngai                             // An I/O error occurred while attempting to close fildes2.
3252b771e32SGou Ngai                             return Err(SystemError::EIO);
3262b771e32SGou Ngai                         }
3272b771e32SGou Ngai                     }
3282b771e32SGou Ngai 
3292b771e32SGou Ngai                     // 尝试获取对应的文件结构体
3302b771e32SGou Ngai                     let file_cp = file.try_clone();
3312b771e32SGou Ngai                     if file_cp.is_none() {
3322b771e32SGou Ngai                         return Err(SystemError::EBADF);
3332b771e32SGou Ngai                     }
3342b771e32SGou Ngai                     // 申请文件描述符,并把文件对象存入其中
335*ab5c8ca4Slogin                     let res = current_pcb()
336*ab5c8ca4Slogin                         .alloc_fd(*file_cp.unwrap(), Some(newfd))
337*ab5c8ca4Slogin                         .map(|x| x as usize);
3382b771e32SGou Ngai 
3392b771e32SGou Ngai                     return res;
3402b771e32SGou Ngai                 }
3412b771e32SGou Ngai                 return Err(SystemError::EBADF);
3422b771e32SGou Ngai             } else {
3432b771e32SGou Ngai                 return Err(SystemError::EBADF);
3442b771e32SGou Ngai             }
3452b771e32SGou Ngai         }
3462b771e32SGou Ngai         // 从pcb获取文件描述符数组失败
3472b771e32SGou Ngai         return Err(SystemError::EMFILE);
3482b771e32SGou Ngai     }
3492b771e32SGou Ngai }
350cde5492fSlogin 
351cde5492fSlogin #[repr(C)]
352cde5492fSlogin #[derive(Debug, Clone, Copy)]
353cde5492fSlogin pub struct IoVec {
354cde5492fSlogin     /// 缓冲区的起始地址
355cde5492fSlogin     pub iov_base: *mut u8,
356cde5492fSlogin     /// 缓冲区的长度
357cde5492fSlogin     pub iov_len: usize,
358cde5492fSlogin }
359cde5492fSlogin 
360cde5492fSlogin /// 用于存储多个来自用户空间的IoVec
361cde5492fSlogin ///
362cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。
363cde5492fSlogin /// TODO:支持分散读写
364cde5492fSlogin #[derive(Debug)]
365cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>);
366cde5492fSlogin 
367cde5492fSlogin impl IoVecs {
368cde5492fSlogin     /// 从用户空间的IoVec中构造IoVecs
369cde5492fSlogin     ///
370cde5492fSlogin     /// @param iov 用户空间的IoVec
371cde5492fSlogin     /// @param iovcnt 用户空间的IoVec的数量
372cde5492fSlogin     /// @param readv 是否为readv系统调用
373cde5492fSlogin     ///
374cde5492fSlogin     /// @return 构造成功返回IoVecs,否则返回错误码
375cde5492fSlogin     pub unsafe fn from_user(
376cde5492fSlogin         iov: *const IoVec,
377cde5492fSlogin         iovcnt: usize,
378cde5492fSlogin         _readv: bool,
379cde5492fSlogin     ) -> Result<Self, SystemError> {
380cde5492fSlogin         // 检查iov指针所在空间是否合法
381cde5492fSlogin         if !verify_area(
382cde5492fSlogin             iov as usize as u64,
383cde5492fSlogin             (iovcnt * core::mem::size_of::<IoVec>()) as u64,
384cde5492fSlogin         ) {
385cde5492fSlogin             return Err(SystemError::EFAULT);
386cde5492fSlogin         }
387cde5492fSlogin 
388cde5492fSlogin         // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放)
389cde5492fSlogin         let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt);
390cde5492fSlogin 
391cde5492fSlogin         let mut slices: Vec<&mut [u8]> = vec![];
392cde5492fSlogin         slices.reserve(iovs.len());
393cde5492fSlogin 
394cde5492fSlogin         for iov in iovs.iter() {
395cde5492fSlogin             if iov.iov_len == 0 {
396cde5492fSlogin                 continue;
397cde5492fSlogin             }
398cde5492fSlogin 
399cde5492fSlogin             if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) {
400cde5492fSlogin                 return Err(SystemError::EFAULT);
401cde5492fSlogin             }
402cde5492fSlogin 
403cde5492fSlogin             slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len));
404cde5492fSlogin         }
405cde5492fSlogin 
406cde5492fSlogin         return Ok(Self(slices));
407cde5492fSlogin     }
408cde5492fSlogin 
409cde5492fSlogin     /// @brief 将IoVecs中的数据聚合到一个缓冲区中
410cde5492fSlogin     ///
411cde5492fSlogin     /// @return 返回聚合后的缓冲区
412cde5492fSlogin     pub fn gather(&self) -> Vec<u8> {
413cde5492fSlogin         let mut buf = Vec::new();
414cde5492fSlogin         for slice in self.0.iter() {
415cde5492fSlogin             buf.extend_from_slice(slice);
416cde5492fSlogin         }
417cde5492fSlogin         return buf;
418cde5492fSlogin     }
419cde5492fSlogin 
420cde5492fSlogin     /// @brief 将给定的数据分散写入到IoVecs中
421cde5492fSlogin     pub fn scatter(&mut self, data: &[u8]) {
422cde5492fSlogin         let mut data: &[u8] = data;
423cde5492fSlogin         for slice in self.0.iter_mut() {
424cde5492fSlogin             let len = core::cmp::min(slice.len(), data.len());
425cde5492fSlogin             if len == 0 {
426cde5492fSlogin                 continue;
427cde5492fSlogin             }
428cde5492fSlogin 
429cde5492fSlogin             slice[..len].copy_from_slice(&data[..len]);
430cde5492fSlogin             data = &data[len..];
431cde5492fSlogin         }
432cde5492fSlogin     }
433cde5492fSlogin 
434cde5492fSlogin     /// @brief 创建与IoVecs等长的缓冲区
435cde5492fSlogin     ///
436cde5492fSlogin     /// @param set_len 是否设置返回的Vec的len。
437cde5492fSlogin     /// 如果为true,则返回的Vec的len为所有IoVec的长度之和;
438cde5492fSlogin     /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和.
439cde5492fSlogin     ///
440cde5492fSlogin     /// @return 返回创建的缓冲区
441cde5492fSlogin     pub fn new_buf(&self, set_len: bool) -> Vec<u8> {
442cde5492fSlogin         let total_len: usize = self.0.iter().map(|slice| slice.len()).sum();
443cde5492fSlogin         let mut buf: Vec<u8> = Vec::with_capacity(total_len);
444cde5492fSlogin 
445cde5492fSlogin         if set_len {
446cde5492fSlogin             unsafe {
447cde5492fSlogin                 buf.set_len(total_len);
448cde5492fSlogin             }
449cde5492fSlogin         }
450cde5492fSlogin         return buf;
451cde5492fSlogin     }
452cde5492fSlogin }
453