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