1004e86ffSlogin use core::ffi::{c_char, CStr}; 2004e86ffSlogin 3*cde5492fSlogin use alloc::{boxed::Box, string::ToString, vec::Vec}; 4004e86ffSlogin 5004e86ffSlogin use crate::{ 6004e86ffSlogin arch::asm::{current::current_pcb, ptrace::user_mode}, 72b771e32SGou Ngai filesystem::vfs::file::FileDescriptorVec, 8004e86ffSlogin include::bindings::bindings::{ 92b771e32SGou Ngai pt_regs, verify_area, AT_REMOVEDIR, PAGE_2M_SIZE, PAGE_4K_SIZE, PROC_MAX_FD_NUM, SEEK_CUR, 102b771e32SGou Ngai SEEK_END, SEEK_MAX, SEEK_SET, 11004e86ffSlogin }, 12004e86ffSlogin io::SeekFrom, 132b771e32SGou Ngai kerror, 142b771e32SGou Ngai syscall::SystemError, 15004e86ffSlogin }; 16004e86ffSlogin 17004e86ffSlogin use super::{ 18004e86ffSlogin core::{do_lseek, do_mkdir, do_open, do_read, do_remove_dir, do_unlink_at, do_write}, 19004e86ffSlogin file::{File, FileMode}, 20004e86ffSlogin Dirent, FileType, ROOT_INODE, 21004e86ffSlogin }; 22004e86ffSlogin 23004e86ffSlogin /// @brief 打开文件 24004e86ffSlogin /// 25004e86ffSlogin /// @param regs->r8 path 文件路径 26004e86ffSlogin /// @param regs->r9 o_flags 打开文件的标志位 27004e86ffSlogin /// 28004e86ffSlogin /// @return u64 文件描述符编号,或者是错误码 29004e86ffSlogin #[no_mangle] 30004e86ffSlogin pub extern "C" fn sys_open(regs: &pt_regs) -> u64 { 31004e86ffSlogin let path: &CStr = unsafe { CStr::from_ptr(regs.r8 as usize as *const c_char) }; 32004e86ffSlogin let path: Result<&str, core::str::Utf8Error> = path.to_str(); 33004e86ffSlogin if path.is_err() { 34676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 35004e86ffSlogin } 36004e86ffSlogin let path: &str = path.unwrap(); 37004e86ffSlogin let flags = regs.r9; 38004e86ffSlogin let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32); 39676b8ef6SMork let r: Result<i32, SystemError> = do_open(path, open_flags); 40004e86ffSlogin 41004e86ffSlogin if r.is_ok() { 42004e86ffSlogin return r.unwrap() as u64; 43004e86ffSlogin } else { 44676b8ef6SMork return r.unwrap_err().to_posix_errno() as u64; 45004e86ffSlogin } 46004e86ffSlogin } 47004e86ffSlogin 48004e86ffSlogin /// @brief 关闭文件的系统调用函数 49004e86ffSlogin /// 50004e86ffSlogin /// @param regs->r8 fd:文件描述符编号 51004e86ffSlogin #[no_mangle] 52004e86ffSlogin pub extern "C" fn sys_close(regs: &pt_regs) -> u64 { 53004e86ffSlogin let fd = regs.r8 as i32; 54676b8ef6SMork let r: Result<(), SystemError> = current_pcb().drop_fd(fd); 55004e86ffSlogin 56004e86ffSlogin if r.is_ok() { 57004e86ffSlogin return 0; 58004e86ffSlogin } else { 59676b8ef6SMork return r.unwrap_err().to_posix_errno() as u64; 60004e86ffSlogin } 61004e86ffSlogin } 62004e86ffSlogin 63004e86ffSlogin /// @brief 读取文件的系统调用函数 64004e86ffSlogin /// 65004e86ffSlogin /// @param regs->r8 文件描述符编号 66004e86ffSlogin /// @param regs->r9 输出缓冲区 67004e86ffSlogin /// @param regs->r10 要读取的长度 68004e86ffSlogin #[no_mangle] 69004e86ffSlogin pub extern "C" fn sys_read(regs: &pt_regs) -> u64 { 70004e86ffSlogin let fd = regs.r8 as i32; 71004e86ffSlogin let buf_vaddr = regs.r9 as usize; 72004e86ffSlogin let len = regs.r10 as usize; 73004e86ffSlogin 74004e86ffSlogin // 判断缓冲区是否来自用户态,进行权限校验 75004e86ffSlogin if user_mode(regs) && unsafe { !verify_area(buf_vaddr as u64, len as u64) } { 76004e86ffSlogin // 来自用户态,而buffer在内核态,这样的操作不被允许 77676b8ef6SMork return SystemError::EPERM.to_posix_errno() as u64; 78004e86ffSlogin } 79004e86ffSlogin 80004e86ffSlogin let buf: &mut [u8] = 81004e86ffSlogin unsafe { core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len) }; 82004e86ffSlogin 83676b8ef6SMork let r: Result<usize, SystemError> = do_read(fd, buf); 84004e86ffSlogin 85004e86ffSlogin if r.is_ok() { 86004e86ffSlogin return r.unwrap() as u64; 87004e86ffSlogin } else { 88676b8ef6SMork return r.unwrap_err().to_posix_errno() as u64; 89004e86ffSlogin } 90004e86ffSlogin } 91004e86ffSlogin 92004e86ffSlogin /// @brief 向文件写入数据的系统调用函数 93004e86ffSlogin /// 94004e86ffSlogin /// @param regs->r8 文件描述符编号 95004e86ffSlogin /// @param regs->r9 输入缓冲区 96004e86ffSlogin /// @param regs->r10 要写入的长度 97004e86ffSlogin #[no_mangle] 98004e86ffSlogin pub extern "C" fn sys_write(regs: &pt_regs) -> u64 { 99004e86ffSlogin let fd = regs.r8 as i32; 100004e86ffSlogin let buf_vaddr = regs.r9 as usize; 101004e86ffSlogin let len = regs.r10 as usize; 102004e86ffSlogin 103004e86ffSlogin // 判断缓冲区是否来自用户态,进行权限校验 104004e86ffSlogin if user_mode(regs) && unsafe { !verify_area(buf_vaddr as u64, len as u64) } { 105004e86ffSlogin // 来自用户态,而buffer在内核态,这样的操作不被允许 106676b8ef6SMork return SystemError::EPERM.to_posix_errno() as u64; 107004e86ffSlogin } 108004e86ffSlogin 109004e86ffSlogin let buf: &[u8] = 110004e86ffSlogin unsafe { core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *mut u8, len) }; 111004e86ffSlogin 112676b8ef6SMork let r: Result<usize, SystemError> = do_write(fd, buf); 113004e86ffSlogin 114004e86ffSlogin if r.is_ok() { 115004e86ffSlogin return r.unwrap() as u64; 116004e86ffSlogin } else { 117676b8ef6SMork return r.unwrap_err().to_posix_errno() as u64; 118004e86ffSlogin } 119004e86ffSlogin } 120004e86ffSlogin 121004e86ffSlogin /// @brief 调整文件访问指针位置的系统调用函数 122004e86ffSlogin /// 123004e86ffSlogin /// @param regs->r8 文件描述符编号 124004e86ffSlogin /// @param regs->r9 调整偏移量 125004e86ffSlogin /// @param regs->r10 调整的模式 126004e86ffSlogin #[no_mangle] 127004e86ffSlogin pub extern "C" fn sys_lseek(regs: &pt_regs) -> u64 { 128004e86ffSlogin let fd = regs.r8 as i32; 129004e86ffSlogin let offset = regs.r9 as i64; 130004e86ffSlogin let whence = regs.r10 as u32; 131004e86ffSlogin 132004e86ffSlogin let w: SeekFrom = match whence { 133004e86ffSlogin SEEK_SET => SeekFrom::SeekSet(offset), 134004e86ffSlogin SEEK_CUR => SeekFrom::SeekCurrent(offset), 135004e86ffSlogin SEEK_END => SeekFrom::SeekEnd(offset), 136004e86ffSlogin SEEK_MAX => SeekFrom::SeekEnd(0), 137676b8ef6SMork _ => return SystemError::EINVAL.to_posix_errno() as u64, 138004e86ffSlogin }; 139004e86ffSlogin 140676b8ef6SMork let r: Result<usize, SystemError> = do_lseek(fd, w); 141004e86ffSlogin if r.is_ok() { 142004e86ffSlogin return r.unwrap() as u64; 143004e86ffSlogin } else { 144676b8ef6SMork return r.unwrap_err().to_posix_errno() as u64; 145004e86ffSlogin } 146004e86ffSlogin } 147004e86ffSlogin 148004e86ffSlogin /// @brief 切换工作目录 149004e86ffSlogin /// 150004e86ffSlogin /// @param dest_path 目标路径 151004e86ffSlogin /// 152004e86ffSlogin /// @return 返回码 描述 153004e86ffSlogin /// 0 | 成功 154004e86ffSlogin /// 155004e86ffSlogin /// EACCESS | 权限不足 156004e86ffSlogin /// 157004e86ffSlogin /// ELOOP | 解析path时遇到路径循环 158004e86ffSlogin /// 159004e86ffSlogin /// ENAMETOOLONG | 路径名过长 160004e86ffSlogin /// 161004e86ffSlogin /// ENOENT | 目标文件或目录不存在 162004e86ffSlogin /// 163004e86ffSlogin /// ENODIR | 检索期间发现非目录项 164004e86ffSlogin /// 165004e86ffSlogin /// ENOMEM | 系统内存不足 166004e86ffSlogin /// 167004e86ffSlogin /// EFAULT | 错误的地址 168004e86ffSlogin /// 169004e86ffSlogin /// ENAMETOOLONG | 路径过长 170004e86ffSlogin #[no_mangle] 171004e86ffSlogin pub extern "C" fn sys_chdir(regs: &pt_regs) -> u64 { 172004e86ffSlogin if regs.r8 == 0 { 173676b8ef6SMork return SystemError::EFAULT.to_posix_errno() as u64; 174004e86ffSlogin } 175004e86ffSlogin let ptr = regs.r8 as usize as *const c_char; 176004e86ffSlogin // 权限校验 177004e86ffSlogin if ptr.is_null() 178004e86ffSlogin || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) }) 179004e86ffSlogin { 180676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 181004e86ffSlogin } 182004e86ffSlogin 183004e86ffSlogin let dest_path: &CStr = unsafe { CStr::from_ptr(ptr) }; 184004e86ffSlogin let dest_path: Result<&str, core::str::Utf8Error> = dest_path.to_str(); 185004e86ffSlogin 186004e86ffSlogin if dest_path.is_err() { 187676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 188004e86ffSlogin } 189004e86ffSlogin 190004e86ffSlogin let dest_path: &str = dest_path.unwrap(); 191004e86ffSlogin 192004e86ffSlogin if dest_path.len() == 0 { 193676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 194004e86ffSlogin } else if dest_path.len() >= PAGE_4K_SIZE as usize { 195676b8ef6SMork return SystemError::ENAMETOOLONG.to_posix_errno() as u64; 196004e86ffSlogin } 197004e86ffSlogin 198004e86ffSlogin let path = Box::new(dest_path.clone()); 199004e86ffSlogin let inode = match ROOT_INODE().lookup(&path) { 200004e86ffSlogin Err(e) => { 201676b8ef6SMork kerror!("Change Directory Failed, Error = {:?}", e); 202676b8ef6SMork return SystemError::ENOENT.to_posix_errno() as u64; 203004e86ffSlogin } 204004e86ffSlogin Ok(i) => i, 205004e86ffSlogin }; 206004e86ffSlogin 207004e86ffSlogin match inode.metadata() { 208004e86ffSlogin Err(e) => { 209676b8ef6SMork kerror!("INode Get MetaData Failed, Error = {:?}", e); 210676b8ef6SMork return SystemError::ENOENT.to_posix_errno() as u64; 211004e86ffSlogin } 212004e86ffSlogin Ok(i) => { 213004e86ffSlogin if let FileType::Dir = i.file_type { 214004e86ffSlogin return 0; 215004e86ffSlogin } else { 216676b8ef6SMork return SystemError::ENOTDIR.to_posix_errno() as u64; 217004e86ffSlogin } 218004e86ffSlogin } 219004e86ffSlogin } 220004e86ffSlogin } 221004e86ffSlogin 222004e86ffSlogin /// @brief 获取目录中的数据 223004e86ffSlogin /// 224004e86ffSlogin /// @param fd 文件描述符号 225004e86ffSlogin /// @return uint64_t dirent的总大小 226004e86ffSlogin #[no_mangle] 227004e86ffSlogin pub extern "C" fn sys_getdents(regs: &pt_regs) -> u64 { 228004e86ffSlogin let fd = regs.r8 as i32; 229004e86ffSlogin let count = regs.r10 as i64; 230004e86ffSlogin let dirent = match unsafe { (regs.r9 as usize as *mut Dirent).as_mut() } { 231004e86ffSlogin None => { 232004e86ffSlogin return 0; 233004e86ffSlogin } 234004e86ffSlogin Some(dirent) => dirent, 235004e86ffSlogin }; 236004e86ffSlogin 237004e86ffSlogin if fd < 0 || fd as u32 > PROC_MAX_FD_NUM { 238676b8ef6SMork return SystemError::EBADF.to_posix_errno() as u64; 239004e86ffSlogin } 240004e86ffSlogin 241004e86ffSlogin if count < 0 { 242676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 243004e86ffSlogin } 244004e86ffSlogin 245004e86ffSlogin // 获取fd 246004e86ffSlogin let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) { 247004e86ffSlogin None => { 248676b8ef6SMork return SystemError::EBADF.to_posix_errno() as u64; 249004e86ffSlogin } 250004e86ffSlogin Some(file) => file, 251004e86ffSlogin }; 252004e86ffSlogin // kdebug!("file={file:?}"); 253004e86ffSlogin 254004e86ffSlogin return match file.readdir(dirent) { 255004e86ffSlogin Err(_) => 0, 256004e86ffSlogin Ok(len) => len, 257004e86ffSlogin }; 258004e86ffSlogin } 259004e86ffSlogin 260004e86ffSlogin /// @brief 创建文件夹 261004e86ffSlogin /// 262004e86ffSlogin /// @param path(r8) 路径 / mode(r9) 模式 263004e86ffSlogin /// 264004e86ffSlogin /// @return uint64_t 负数错误码 / 0表示成功 265004e86ffSlogin #[no_mangle] 266004e86ffSlogin pub extern "C" fn sys_mkdir(regs: &pt_regs) -> u64 { 267004e86ffSlogin let ptr = regs.r8 as usize as *const c_char; 268004e86ffSlogin if ptr.is_null() 269004e86ffSlogin || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) }) 270004e86ffSlogin { 271676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 272004e86ffSlogin } 273004e86ffSlogin let path: &CStr = unsafe { CStr::from_ptr(ptr) }; 274004e86ffSlogin let path: Result<&str, core::str::Utf8Error> = path.to_str(); 275004e86ffSlogin let mode = regs.r9; 276004e86ffSlogin 277004e86ffSlogin if path.is_err() { 278676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 279004e86ffSlogin } 280004e86ffSlogin 281004e86ffSlogin let path = &path.unwrap().to_string(); 282004e86ffSlogin if path.trim() == "" { 283676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 284004e86ffSlogin } 285004e86ffSlogin 28684407d36Slogin return match do_mkdir(&path.trim(), FileMode::from_bits_truncate(mode as u32)) { 287004e86ffSlogin Err(err) => { 288676b8ef6SMork kerror!("Failed in do_mkdir, Error Code = {:#?}", err); 289676b8ef6SMork err.to_posix_errno() as u64 290004e86ffSlogin } 291004e86ffSlogin Ok(_) => 0, 292004e86ffSlogin }; 293004e86ffSlogin } 294004e86ffSlogin 295004e86ffSlogin ///@brief 删除文件夹、取消文件的链接、删除文件的系统调用 296004e86ffSlogin /// 297004e86ffSlogin ///@param regs->r8 dfd 进程相对路径基准目录的文件描述符(见fcntl.h) 298004e86ffSlogin /// 299004e86ffSlogin ///@param regs->r9 路径名称字符串 300004e86ffSlogin /// 301004e86ffSlogin ///@param regs->r10 flag 预留的标志位,暂时未使用,请置为0。 302004e86ffSlogin /// 303004e86ffSlogin ///@return uint64_t 错误码 304004e86ffSlogin #[no_mangle] 305004e86ffSlogin pub extern "C" fn sys_unlink_at(regs: &pt_regs) -> u64 { 306004e86ffSlogin let _dfd = regs.r8; 307004e86ffSlogin let ptr = regs.r9 as usize as *const c_char; 308004e86ffSlogin if ptr.is_null() 309004e86ffSlogin || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) }) 310004e86ffSlogin { 311676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 312004e86ffSlogin } 313004e86ffSlogin let path: &CStr = unsafe { CStr::from_ptr(ptr) }; 314004e86ffSlogin let path: Result<&str, core::str::Utf8Error> = path.to_str(); 315004e86ffSlogin let flag = regs.r10; 316004e86ffSlogin if path.is_err() { 317676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 318004e86ffSlogin } 319004e86ffSlogin 320004e86ffSlogin let path = &path.unwrap().to_string(); 321004e86ffSlogin // kdebug!("sys_unlink_at={path:?}"); 322004e86ffSlogin if (flag & (!(AT_REMOVEDIR as u64))) != 0_u64 { 323676b8ef6SMork return SystemError::EINVAL.to_posix_errno() as u64; 324004e86ffSlogin } 325004e86ffSlogin 326004e86ffSlogin if (flag & (AT_REMOVEDIR as u64)) > 0 { 327004e86ffSlogin // kdebug!("rmdir"); 328004e86ffSlogin match do_remove_dir(&path) { 329004e86ffSlogin Err(err) => { 330676b8ef6SMork kerror!("Failed to Remove Directory, Error Code = {:?}", err); 331676b8ef6SMork return err.to_posix_errno() as u64; 332004e86ffSlogin } 333004e86ffSlogin Ok(_) => { 334004e86ffSlogin return 0; 335004e86ffSlogin } 336004e86ffSlogin } 337004e86ffSlogin } 338004e86ffSlogin 339004e86ffSlogin // kdebug!("rm"); 340004e86ffSlogin match do_unlink_at(&path, FileMode::from_bits_truncate(flag as u32)) { 341004e86ffSlogin Err(err) => { 342676b8ef6SMork kerror!("Failed to Remove Directory, Error Code = {:?}", err); 343676b8ef6SMork return err.to_posix_errno() as u64; 344004e86ffSlogin } 345004e86ffSlogin Ok(_) => { 346004e86ffSlogin return 0; 347004e86ffSlogin } 348004e86ffSlogin } 349004e86ffSlogin } 3502b771e32SGou Ngai 3512b771e32SGou Ngai fn do_dup(oldfd: i32) -> Result<i32, SystemError> { 3522b771e32SGou Ngai if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 3532b771e32SGou Ngai // 获得当前文件描述符数组 3542b771e32SGou Ngai // 确认oldfd是否有效 3552b771e32SGou Ngai if FileDescriptorVec::validate_fd(oldfd) { 3562b771e32SGou Ngai if let Some(file) = &fds.fds[oldfd as usize] { 3572b771e32SGou Ngai // 尝试获取对应的文件结构体 3582b771e32SGou Ngai let file_cp = (file).try_clone(); 3592b771e32SGou Ngai if file_cp.is_none() { 3602b771e32SGou Ngai return Err(SystemError::EBADF); 3612b771e32SGou Ngai } 3622b771e32SGou Ngai let res = current_pcb().alloc_fd(*file_cp.unwrap(), None); 3632b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 3642b771e32SGou Ngai return res; 3652b771e32SGou Ngai } 3662b771e32SGou Ngai // oldfd对应的文件不存在 3672b771e32SGou Ngai return Err(SystemError::EBADF); 3682b771e32SGou Ngai } 3692b771e32SGou Ngai return Err(SystemError::EBADF); 3702b771e32SGou Ngai } else { 3712b771e32SGou Ngai return Err(SystemError::EMFILE); 3722b771e32SGou Ngai } 3732b771e32SGou Ngai } 3742b771e32SGou Ngai 3752b771e32SGou Ngai #[no_mangle] 3762b771e32SGou Ngai /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 3772b771e32SGou Ngai pub extern "C" fn sys_dup(regs: &pt_regs) -> u64 { 3782b771e32SGou Ngai let fd: i32 = regs.r8 as i32; 3792b771e32SGou Ngai let r = do_dup(fd); 3802b771e32SGou Ngai if r.is_ok() { 3812b771e32SGou Ngai return r.unwrap() as u64; 3822b771e32SGou Ngai } else { 3832b771e32SGou Ngai return r.unwrap_err().to_posix_errno() as u64; 3842b771e32SGou Ngai } 3852b771e32SGou Ngai } 3862b771e32SGou Ngai 3872b771e32SGou Ngai fn do_dup2(oldfd: i32, newfd: i32) -> Result<i32, SystemError> { 3882b771e32SGou Ngai if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 3892b771e32SGou Ngai // 获得当前文件描述符数组 3902b771e32SGou Ngai if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) { 3912b771e32SGou Ngai //确认oldfd, newid是否有效 3922b771e32SGou Ngai if oldfd == newfd { 3932b771e32SGou Ngai // 若oldfd与newfd相等 3942b771e32SGou Ngai return Ok(newfd); 3952b771e32SGou Ngai } 3962b771e32SGou Ngai 3972b771e32SGou Ngai if let Some(file) = &fds.fds[oldfd as usize] { 3982b771e32SGou Ngai if fds.fds[newfd as usize].is_some() { 3992b771e32SGou Ngai // close newfd 4002b771e32SGou Ngai if let Err(_) = current_pcb().drop_fd(newfd) { 4012b771e32SGou Ngai // An I/O error occurred while attempting to close fildes2. 4022b771e32SGou Ngai return Err(SystemError::EIO); 4032b771e32SGou Ngai } 4042b771e32SGou Ngai } 4052b771e32SGou Ngai 4062b771e32SGou Ngai // 尝试获取对应的文件结构体 4072b771e32SGou Ngai let file_cp = file.try_clone(); 4082b771e32SGou Ngai if file_cp.is_none() { 4092b771e32SGou Ngai return Err(SystemError::EBADF); 4102b771e32SGou Ngai } 4112b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 4122b771e32SGou Ngai let res = current_pcb().alloc_fd(*file_cp.unwrap(), Some(newfd)); 4132b771e32SGou Ngai 4142b771e32SGou Ngai return res; 4152b771e32SGou Ngai } 4162b771e32SGou Ngai return Err(SystemError::EBADF); 4172b771e32SGou Ngai } else { 4182b771e32SGou Ngai return Err(SystemError::EBADF); 4192b771e32SGou Ngai } 4202b771e32SGou Ngai } 4212b771e32SGou Ngai // 从pcb获取文件描述符数组失败 4222b771e32SGou Ngai return Err(SystemError::EMFILE); 4232b771e32SGou Ngai } 4242b771e32SGou Ngai 4252b771e32SGou Ngai #[no_mangle] 4262b771e32SGou Ngai /// @brief 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 4272b771e32SGou Ngai /// 并返回新复制的文件结构体对应的fd 4282b771e32SGou Ngai pub extern "C" fn sys_dup2(regs: &pt_regs) -> u64 { 4292b771e32SGou Ngai let ofd = regs.r8 as i32; 4302b771e32SGou Ngai let nfd = regs.r9 as i32; 4312b771e32SGou Ngai let r = do_dup2(ofd, nfd); 4322b771e32SGou Ngai if r.is_ok() { 4332b771e32SGou Ngai return r.unwrap() as u64; 4342b771e32SGou Ngai } else { 4352b771e32SGou Ngai return r.unwrap_err().to_posix_errno() as u64; 4362b771e32SGou Ngai } 4372b771e32SGou Ngai } 438*cde5492fSlogin 439*cde5492fSlogin #[repr(C)] 440*cde5492fSlogin #[derive(Debug, Clone, Copy)] 441*cde5492fSlogin pub struct IoVec { 442*cde5492fSlogin /// 缓冲区的起始地址 443*cde5492fSlogin pub iov_base: *mut u8, 444*cde5492fSlogin /// 缓冲区的长度 445*cde5492fSlogin pub iov_len: usize, 446*cde5492fSlogin } 447*cde5492fSlogin 448*cde5492fSlogin /// 用于存储多个来自用户空间的IoVec 449*cde5492fSlogin /// 450*cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 451*cde5492fSlogin /// TODO:支持分散读写 452*cde5492fSlogin #[derive(Debug)] 453*cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>); 454*cde5492fSlogin 455*cde5492fSlogin impl IoVecs { 456*cde5492fSlogin /// 从用户空间的IoVec中构造IoVecs 457*cde5492fSlogin /// 458*cde5492fSlogin /// @param iov 用户空间的IoVec 459*cde5492fSlogin /// @param iovcnt 用户空间的IoVec的数量 460*cde5492fSlogin /// @param readv 是否为readv系统调用 461*cde5492fSlogin /// 462*cde5492fSlogin /// @return 构造成功返回IoVecs,否则返回错误码 463*cde5492fSlogin pub unsafe fn from_user( 464*cde5492fSlogin iov: *const IoVec, 465*cde5492fSlogin iovcnt: usize, 466*cde5492fSlogin _readv: bool, 467*cde5492fSlogin ) -> Result<Self, SystemError> { 468*cde5492fSlogin // 检查iov指针所在空间是否合法 469*cde5492fSlogin if !verify_area( 470*cde5492fSlogin iov as usize as u64, 471*cde5492fSlogin (iovcnt * core::mem::size_of::<IoVec>()) as u64, 472*cde5492fSlogin ) { 473*cde5492fSlogin return Err(SystemError::EFAULT); 474*cde5492fSlogin } 475*cde5492fSlogin 476*cde5492fSlogin // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 477*cde5492fSlogin let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 478*cde5492fSlogin 479*cde5492fSlogin let mut slices: Vec<&mut [u8]> = vec![]; 480*cde5492fSlogin slices.reserve(iovs.len()); 481*cde5492fSlogin 482*cde5492fSlogin for iov in iovs.iter() { 483*cde5492fSlogin if iov.iov_len == 0 { 484*cde5492fSlogin continue; 485*cde5492fSlogin } 486*cde5492fSlogin 487*cde5492fSlogin if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) { 488*cde5492fSlogin return Err(SystemError::EFAULT); 489*cde5492fSlogin } 490*cde5492fSlogin 491*cde5492fSlogin slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 492*cde5492fSlogin } 493*cde5492fSlogin 494*cde5492fSlogin return Ok(Self(slices)); 495*cde5492fSlogin } 496*cde5492fSlogin 497*cde5492fSlogin /// @brief 将IoVecs中的数据聚合到一个缓冲区中 498*cde5492fSlogin /// 499*cde5492fSlogin /// @return 返回聚合后的缓冲区 500*cde5492fSlogin pub fn gather(&self) -> Vec<u8> { 501*cde5492fSlogin let mut buf = Vec::new(); 502*cde5492fSlogin for slice in self.0.iter() { 503*cde5492fSlogin buf.extend_from_slice(slice); 504*cde5492fSlogin } 505*cde5492fSlogin return buf; 506*cde5492fSlogin } 507*cde5492fSlogin 508*cde5492fSlogin /// @brief 将给定的数据分散写入到IoVecs中 509*cde5492fSlogin pub fn scatter(&mut self, data: &[u8]) { 510*cde5492fSlogin let mut data: &[u8] = data; 511*cde5492fSlogin for slice in self.0.iter_mut() { 512*cde5492fSlogin let len = core::cmp::min(slice.len(), data.len()); 513*cde5492fSlogin if len == 0 { 514*cde5492fSlogin continue; 515*cde5492fSlogin } 516*cde5492fSlogin 517*cde5492fSlogin slice[..len].copy_from_slice(&data[..len]); 518*cde5492fSlogin data = &data[len..]; 519*cde5492fSlogin } 520*cde5492fSlogin } 521*cde5492fSlogin 522*cde5492fSlogin /// @brief 创建与IoVecs等长的缓冲区 523*cde5492fSlogin /// 524*cde5492fSlogin /// @param set_len 是否设置返回的Vec的len。 525*cde5492fSlogin /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 526*cde5492fSlogin /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 527*cde5492fSlogin /// 528*cde5492fSlogin /// @return 返回创建的缓冲区 529*cde5492fSlogin pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 530*cde5492fSlogin let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 531*cde5492fSlogin let mut buf: Vec<u8> = Vec::with_capacity(total_len); 532*cde5492fSlogin 533*cde5492fSlogin if set_len { 534*cde5492fSlogin unsafe { 535*cde5492fSlogin buf.set_len(total_len); 536*cde5492fSlogin } 537*cde5492fSlogin } 538*cde5492fSlogin return buf; 539*cde5492fSlogin } 540*cde5492fSlogin } 541