1ab5c8ca4Slogin use alloc::{boxed::Box, sync::Arc, vec::Vec}; 2004e86ffSlogin 3004e86ffSlogin use crate::{ 4aa0367d6SLoGin arch::asm::current::current_pcb, 52b771e32SGou Ngai filesystem::vfs::file::FileDescriptorVec, 6aa0367d6SLoGin include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM}, 7004e86ffSlogin io::SeekFrom, 82b771e32SGou Ngai kerror, 9ab5c8ca4Slogin syscall::{Syscall, SystemError}, 10004e86ffSlogin }; 11004e86ffSlogin 12004e86ffSlogin use super::{ 13ab5c8ca4Slogin core::{do_mkdir, do_remove_dir, do_unlink_at}, 14*6d81180bSLoGin fcntl::{FcntlCommand, FD_CLOEXEC}, 15004e86ffSlogin file::{File, FileMode}, 16ab5c8ca4Slogin utils::rsplit_path, 17ab5c8ca4Slogin Dirent, FileType, IndexNode, ROOT_INODE, 18004e86ffSlogin }; 19004e86ffSlogin 20ab5c8ca4Slogin pub const SEEK_SET: u32 = 0; 21ab5c8ca4Slogin pub const SEEK_CUR: u32 = 1; 22ab5c8ca4Slogin pub const SEEK_END: u32 = 2; 23ab5c8ca4Slogin pub const SEEK_MAX: u32 = 3; 24004e86ffSlogin 25ab5c8ca4Slogin impl Syscall { 26ab5c8ca4Slogin /// @brief 为当前进程打开一个文件 27ab5c8ca4Slogin /// 28ab5c8ca4Slogin /// @param path 文件路径 29ab5c8ca4Slogin /// @param o_flags 打开文件的标志位 30ab5c8ca4Slogin /// 31ab5c8ca4Slogin /// @return 文件描述符编号,或者是错误码 32ab5c8ca4Slogin pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> { 33*6d81180bSLoGin // kdebug!("open: path: {}, mode: {:?}", path, mode); 34ab5c8ca4Slogin // 文件名过长 35ab5c8ca4Slogin if path.len() > PAGE_4K_SIZE as usize { 36ab5c8ca4Slogin return Err(SystemError::ENAMETOOLONG); 37ab5c8ca4Slogin } 38ab5c8ca4Slogin 39ab5c8ca4Slogin let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path); 40ab5c8ca4Slogin 41ab5c8ca4Slogin let inode: Arc<dyn IndexNode> = if inode.is_err() { 42ab5c8ca4Slogin let errno = inode.unwrap_err(); 43ab5c8ca4Slogin // 文件不存在,且需要创建 44ab5c8ca4Slogin if mode.contains(FileMode::O_CREAT) 45ab5c8ca4Slogin && !mode.contains(FileMode::O_DIRECTORY) 46ab5c8ca4Slogin && errno == SystemError::ENOENT 47ab5c8ca4Slogin { 48ab5c8ca4Slogin let (filename, parent_path) = rsplit_path(path); 49ab5c8ca4Slogin // 查找父目录 50ab5c8ca4Slogin let parent_inode: Arc<dyn IndexNode> = 51ab5c8ca4Slogin ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; 52ab5c8ca4Slogin // 创建文件 53ab5c8ca4Slogin let inode: Arc<dyn IndexNode> = 54ab5c8ca4Slogin parent_inode.create(filename, FileType::File, 0o777)?; 55ab5c8ca4Slogin inode 56004e86ffSlogin } else { 57ab5c8ca4Slogin // 不需要创建文件,因此返回错误码 58ab5c8ca4Slogin return Err(errno); 59004e86ffSlogin } 60004e86ffSlogin } else { 61ab5c8ca4Slogin inode.unwrap() 62004e86ffSlogin }; 63004e86ffSlogin 64ab5c8ca4Slogin let file_type: FileType = inode.metadata()?.file_type; 65ab5c8ca4Slogin // 如果要打开的是文件夹,而目标不是文件夹 66ab5c8ca4Slogin if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir { 67ab5c8ca4Slogin return Err(SystemError::ENOTDIR); 68004e86ffSlogin } 69ab5c8ca4Slogin 70ab5c8ca4Slogin // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件 71ab5c8ca4Slogin if mode.contains(FileMode::O_TRUNC) 72ab5c8ca4Slogin && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY)) 73ab5c8ca4Slogin && file_type == FileType::File 74ab5c8ca4Slogin { 75ab5c8ca4Slogin inode.truncate(0)?; 76ab5c8ca4Slogin } 77ab5c8ca4Slogin 78ab5c8ca4Slogin // 创建文件对象 79ab5c8ca4Slogin let mut file: File = File::new(inode, mode)?; 80ab5c8ca4Slogin 81ab5c8ca4Slogin // 打开模式为“追加” 82ab5c8ca4Slogin if mode.contains(FileMode::O_APPEND) { 83ab5c8ca4Slogin file.lseek(SeekFrom::SeekEnd(0))?; 84ab5c8ca4Slogin } 85ab5c8ca4Slogin 86ab5c8ca4Slogin // 把文件对象存入pcb 87*6d81180bSLoGin let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize); 88*6d81180bSLoGin // kdebug!("open: fd: {:?}", r); 89*6d81180bSLoGin return r; 90ab5c8ca4Slogin } 91ab5c8ca4Slogin 92ab5c8ca4Slogin /// @brief 关闭文件 93ab5c8ca4Slogin /// 94ab5c8ca4Slogin /// @param fd 文件描述符编号 95ab5c8ca4Slogin /// 96ab5c8ca4Slogin /// @return 成功返回0,失败返回错误码 97ab5c8ca4Slogin pub fn close(fd: usize) -> Result<usize, SystemError> { 98*6d81180bSLoGin // kdebug!("syscall::close: fd: {}", fd); 99ab5c8ca4Slogin return current_pcb().drop_fd(fd as i32).map(|_| 0); 100ab5c8ca4Slogin } 101ab5c8ca4Slogin 102ab5c8ca4Slogin /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 103ab5c8ca4Slogin /// 104ab5c8ca4Slogin /// @param fd 文件描述符编号 105ab5c8ca4Slogin /// @param buf 输出缓冲区。 106ab5c8ca4Slogin /// 107ab5c8ca4Slogin /// @return Ok(usize) 成功读取的数据的字节数 108ab5c8ca4Slogin /// @return Err(SystemError) 读取失败,返回posix错误码 109ab5c8ca4Slogin pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 110*6d81180bSLoGin // kdebug!("syscall::read: fd: {}, len={}", fd, buf.len()); 111ab5c8ca4Slogin let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 112ab5c8ca4Slogin if file.is_none() { 113ab5c8ca4Slogin return Err(SystemError::EBADF); 114ab5c8ca4Slogin } 115ab5c8ca4Slogin let file: &mut File = file.unwrap(); 116ab5c8ca4Slogin 117ab5c8ca4Slogin return file.read(buf.len(), buf); 118ab5c8ca4Slogin } 119ab5c8ca4Slogin 120ab5c8ca4Slogin /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 121ab5c8ca4Slogin /// 122ab5c8ca4Slogin /// @param fd 文件描述符编号 123ab5c8ca4Slogin /// @param buf 输入缓冲区。 124ab5c8ca4Slogin /// 125ab5c8ca4Slogin /// @return Ok(usize) 成功写入的数据的字节数 126ab5c8ca4Slogin /// @return Err(SystemError) 写入失败,返回posix错误码 127ab5c8ca4Slogin pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> { 128*6d81180bSLoGin // kdebug!("syscall::write: fd: {}, len={}", fd, buf.len()); 129ab5c8ca4Slogin let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 130ab5c8ca4Slogin if file.is_none() { 131ab5c8ca4Slogin return Err(SystemError::EBADF); 132ab5c8ca4Slogin } 133ab5c8ca4Slogin let file: &mut File = file.unwrap(); 134ab5c8ca4Slogin 135ab5c8ca4Slogin return file.write(buf.len(), buf); 136ab5c8ca4Slogin } 137ab5c8ca4Slogin 138ab5c8ca4Slogin /// @brief 调整文件操作指针的位置 139ab5c8ca4Slogin /// 140ab5c8ca4Slogin /// @param fd 文件描述符编号 141ab5c8ca4Slogin /// @param seek 调整的方式 142ab5c8ca4Slogin /// 143ab5c8ca4Slogin /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量 144ab5c8ca4Slogin /// @return Err(SystemError) 调整失败,返回posix错误码 145ab5c8ca4Slogin pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> { 146*6d81180bSLoGin // kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek); 147ab5c8ca4Slogin let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 148ab5c8ca4Slogin if file.is_none() { 149ab5c8ca4Slogin return Err(SystemError::EBADF); 150ab5c8ca4Slogin } 151ab5c8ca4Slogin let file: &mut File = file.unwrap(); 152ab5c8ca4Slogin return file.lseek(seek); 153004e86ffSlogin } 154004e86ffSlogin 155004e86ffSlogin /// @brief 切换工作目录 156004e86ffSlogin /// 157004e86ffSlogin /// @param dest_path 目标路径 158004e86ffSlogin /// 159004e86ffSlogin /// @return 返回码 描述 160004e86ffSlogin /// 0 | 成功 161004e86ffSlogin /// 162004e86ffSlogin /// EACCESS | 权限不足 163004e86ffSlogin /// 164004e86ffSlogin /// ELOOP | 解析path时遇到路径循环 165004e86ffSlogin /// 166004e86ffSlogin /// ENAMETOOLONG | 路径名过长 167004e86ffSlogin /// 168004e86ffSlogin /// ENOENT | 目标文件或目录不存在 169004e86ffSlogin /// 170004e86ffSlogin /// ENODIR | 检索期间发现非目录项 171004e86ffSlogin /// 172004e86ffSlogin /// ENOMEM | 系统内存不足 173004e86ffSlogin /// 174004e86ffSlogin /// EFAULT | 错误的地址 175004e86ffSlogin /// 176004e86ffSlogin /// ENAMETOOLONG | 路径过长 177ab5c8ca4Slogin pub fn chdir(dest_path: &str) -> Result<usize, SystemError> { 178ab5c8ca4Slogin // Copy path to kernel space to avoid some security issues 179ab5c8ca4Slogin let path: Box<&str> = Box::new(dest_path); 180004e86ffSlogin let inode = match ROOT_INODE().lookup(&path) { 181004e86ffSlogin Err(e) => { 182676b8ef6SMork kerror!("Change Directory Failed, Error = {:?}", e); 183ab5c8ca4Slogin return Err(SystemError::ENOENT); 184004e86ffSlogin } 185004e86ffSlogin Ok(i) => i, 186004e86ffSlogin }; 187004e86ffSlogin 188004e86ffSlogin match inode.metadata() { 189004e86ffSlogin Err(e) => { 190676b8ef6SMork kerror!("INode Get MetaData Failed, Error = {:?}", e); 191ab5c8ca4Slogin return Err(SystemError::ENOENT); 192004e86ffSlogin } 193004e86ffSlogin Ok(i) => { 194004e86ffSlogin if let FileType::Dir = i.file_type { 195ab5c8ca4Slogin return Ok(0); 196004e86ffSlogin } else { 197ab5c8ca4Slogin return Err(SystemError::ENOTDIR); 198004e86ffSlogin } 199004e86ffSlogin } 200004e86ffSlogin } 201004e86ffSlogin } 202004e86ffSlogin 203004e86ffSlogin /// @brief 获取目录中的数据 204004e86ffSlogin /// 205ab5c8ca4Slogin /// TODO: 这个函数的语义与Linux不一致,需要修改!!! 206ab5c8ca4Slogin /// 207004e86ffSlogin /// @param fd 文件描述符号 208ab5c8ca4Slogin /// @param buf 输出缓冲区 209ab5c8ca4Slogin /// 210ab5c8ca4Slogin /// @return 成功返回读取的字节数,失败返回错误码 211ab5c8ca4Slogin pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 212ab5c8ca4Slogin let dirent = 213ab5c8ca4Slogin unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?; 214004e86ffSlogin 215004e86ffSlogin if fd < 0 || fd as u32 > PROC_MAX_FD_NUM { 216ab5c8ca4Slogin return Err(SystemError::EBADF); 217004e86ffSlogin } 218004e86ffSlogin 219004e86ffSlogin // 获取fd 220004e86ffSlogin let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) { 221004e86ffSlogin None => { 222ab5c8ca4Slogin return Err(SystemError::EBADF); 223004e86ffSlogin } 224004e86ffSlogin Some(file) => file, 225004e86ffSlogin }; 226004e86ffSlogin // kdebug!("file={file:?}"); 227004e86ffSlogin 228ab5c8ca4Slogin return file.readdir(dirent).map(|x| x as usize); 229004e86ffSlogin } 230004e86ffSlogin 231004e86ffSlogin /// @brief 创建文件夹 232004e86ffSlogin /// 233004e86ffSlogin /// @param path(r8) 路径 / mode(r9) 模式 234004e86ffSlogin /// 235004e86ffSlogin /// @return uint64_t 负数错误码 / 0表示成功 236ab5c8ca4Slogin pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> { 237ab5c8ca4Slogin return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); 238004e86ffSlogin } 239004e86ffSlogin 240ab5c8ca4Slogin /// **删除文件夹、取消文件的链接、删除文件的系统调用** 241004e86ffSlogin /// 242ab5c8ca4Slogin /// ## 参数 243004e86ffSlogin /// 244ab5c8ca4Slogin /// - `dirfd`:文件夹的文件描述符.目前暂未实现 245ab5c8ca4Slogin /// - `pathname`:文件夹的路径 246ab5c8ca4Slogin /// - `flags`:标志位 247004e86ffSlogin /// 248004e86ffSlogin /// 249ab5c8ca4Slogin pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> { 250004e86ffSlogin // kdebug!("sys_unlink_at={path:?}"); 251ab5c8ca4Slogin if (flags & (!AT_REMOVEDIR)) != 0 { 252ab5c8ca4Slogin return Err(SystemError::EINVAL); 253004e86ffSlogin } 254004e86ffSlogin 255ab5c8ca4Slogin if (flags & AT_REMOVEDIR) > 0 { 256004e86ffSlogin // kdebug!("rmdir"); 257ab5c8ca4Slogin match do_remove_dir(&pathname) { 258004e86ffSlogin Err(err) => { 259676b8ef6SMork kerror!("Failed to Remove Directory, Error Code = {:?}", err); 260ab5c8ca4Slogin return Err(err); 261004e86ffSlogin } 262004e86ffSlogin Ok(_) => { 263ab5c8ca4Slogin return Ok(0); 264004e86ffSlogin } 265004e86ffSlogin } 266004e86ffSlogin } 267004e86ffSlogin 268ab5c8ca4Slogin match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) { 269004e86ffSlogin Err(err) => { 270676b8ef6SMork kerror!("Failed to Remove Directory, Error Code = {:?}", err); 271ab5c8ca4Slogin return Err(err); 272004e86ffSlogin } 273004e86ffSlogin Ok(_) => { 274ab5c8ca4Slogin return Ok(0); 275004e86ffSlogin } 276004e86ffSlogin } 277004e86ffSlogin } 2782b771e32SGou Ngai 279ab5c8ca4Slogin /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 280ab5c8ca4Slogin pub fn dup(oldfd: i32) -> Result<usize, SystemError> { 2812b771e32SGou Ngai if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 2822b771e32SGou Ngai // 获得当前文件描述符数组 2832b771e32SGou Ngai // 确认oldfd是否有效 2842b771e32SGou Ngai if FileDescriptorVec::validate_fd(oldfd) { 2852b771e32SGou Ngai if let Some(file) = &fds.fds[oldfd as usize] { 2862b771e32SGou Ngai // 尝试获取对应的文件结构体 287ab5c8ca4Slogin let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?; 288ab5c8ca4Slogin 2892b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 290ab5c8ca4Slogin let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize); 2912b771e32SGou Ngai return res; 2922b771e32SGou Ngai } 2932b771e32SGou Ngai // oldfd对应的文件不存在 2942b771e32SGou Ngai return Err(SystemError::EBADF); 2952b771e32SGou Ngai } 2962b771e32SGou Ngai return Err(SystemError::EBADF); 2972b771e32SGou Ngai } else { 2982b771e32SGou Ngai return Err(SystemError::EMFILE); 2992b771e32SGou Ngai } 3002b771e32SGou Ngai } 3012b771e32SGou Ngai 302ab5c8ca4Slogin /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 303ab5c8ca4Slogin /// 并返回新复制的文件结构体对应的fd. 304ab5c8ca4Slogin /// 如果新fd已经打开,则会先关闭新fd. 305ab5c8ca4Slogin /// 306ab5c8ca4Slogin /// ## 参数 307ab5c8ca4Slogin /// 308ab5c8ca4Slogin /// - `oldfd`:旧文件描述符 309ab5c8ca4Slogin /// - `newfd`:新文件描述符 310ab5c8ca4Slogin /// 311ab5c8ca4Slogin /// ## 返回值 312ab5c8ca4Slogin /// 313ab5c8ca4Slogin /// - 成功:新文件描述符 314ab5c8ca4Slogin /// - 失败:错误码 315ab5c8ca4Slogin pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> { 3162b771e32SGou Ngai if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 3172b771e32SGou Ngai // 获得当前文件描述符数组 3182b771e32SGou Ngai if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) { 3192b771e32SGou Ngai //确认oldfd, newid是否有效 3202b771e32SGou Ngai if oldfd == newfd { 3212b771e32SGou Ngai // 若oldfd与newfd相等 322ab5c8ca4Slogin return Ok(newfd as usize); 3232b771e32SGou Ngai } 3242b771e32SGou Ngai 3252b771e32SGou Ngai if let Some(file) = &fds.fds[oldfd as usize] { 3262b771e32SGou Ngai if fds.fds[newfd as usize].is_some() { 3272b771e32SGou Ngai // close newfd 3282b771e32SGou Ngai if let Err(_) = current_pcb().drop_fd(newfd) { 3292b771e32SGou Ngai // An I/O error occurred while attempting to close fildes2. 3302b771e32SGou Ngai return Err(SystemError::EIO); 3312b771e32SGou Ngai } 3322b771e32SGou Ngai } 3332b771e32SGou Ngai 3342b771e32SGou Ngai // 尝试获取对应的文件结构体 3352b771e32SGou Ngai let file_cp = file.try_clone(); 3362b771e32SGou Ngai if file_cp.is_none() { 3372b771e32SGou Ngai return Err(SystemError::EBADF); 3382b771e32SGou Ngai } 3392b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 340ab5c8ca4Slogin let res = current_pcb() 341ab5c8ca4Slogin .alloc_fd(*file_cp.unwrap(), Some(newfd)) 342ab5c8ca4Slogin .map(|x| x as usize); 3432b771e32SGou Ngai 3442b771e32SGou Ngai return res; 3452b771e32SGou Ngai } 3462b771e32SGou Ngai return Err(SystemError::EBADF); 3472b771e32SGou Ngai } else { 3482b771e32SGou Ngai return Err(SystemError::EBADF); 3492b771e32SGou Ngai } 3502b771e32SGou Ngai } 3512b771e32SGou Ngai // 从pcb获取文件描述符数组失败 3522b771e32SGou Ngai return Err(SystemError::EMFILE); 3532b771e32SGou Ngai } 354*6d81180bSLoGin 355*6d81180bSLoGin /// # fcntl 356*6d81180bSLoGin /// 357*6d81180bSLoGin /// ## 参数 358*6d81180bSLoGin /// 359*6d81180bSLoGin /// - `fd`:文件描述符 360*6d81180bSLoGin /// - `cmd`:命令 361*6d81180bSLoGin /// - `arg`:参数 362*6d81180bSLoGin pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> { 363*6d81180bSLoGin match cmd { 364*6d81180bSLoGin FcntlCommand::DupFd => { 365*6d81180bSLoGin if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD { 366*6d81180bSLoGin return Err(SystemError::EBADF); 367*6d81180bSLoGin } 368*6d81180bSLoGin let arg = arg as usize; 369*6d81180bSLoGin for i in arg..FileDescriptorVec::PROCESS_MAX_FD { 370*6d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 371*6d81180bSLoGin if fds.fds[i as usize].is_none() { 372*6d81180bSLoGin return Self::dup2(fd, i as i32); 373*6d81180bSLoGin } 374*6d81180bSLoGin } 375*6d81180bSLoGin } 376*6d81180bSLoGin return Err(SystemError::EMFILE); 377*6d81180bSLoGin } 378*6d81180bSLoGin FcntlCommand::GetFd => { 379*6d81180bSLoGin // Get file descriptor flags. 380*6d81180bSLoGin 381*6d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 382*6d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 383*6d81180bSLoGin if let Some(file) = &fds.fds[fd as usize] { 384*6d81180bSLoGin if file.close_on_exec() { 385*6d81180bSLoGin return Ok(FD_CLOEXEC as usize); 386*6d81180bSLoGin } 387*6d81180bSLoGin } 388*6d81180bSLoGin return Err(SystemError::EBADF); 389*6d81180bSLoGin } 390*6d81180bSLoGin } 391*6d81180bSLoGin return Err(SystemError::EBADF); 392*6d81180bSLoGin } 393*6d81180bSLoGin FcntlCommand::SetFd => { 394*6d81180bSLoGin // Set file descriptor flags. 395*6d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 396*6d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 397*6d81180bSLoGin if let Some(file) = &mut fds.fds[fd as usize] { 398*6d81180bSLoGin let arg = arg as u32; 399*6d81180bSLoGin if arg & FD_CLOEXEC != 0 { 400*6d81180bSLoGin file.set_close_on_exec(true); 401*6d81180bSLoGin } else { 402*6d81180bSLoGin file.set_close_on_exec(false); 403*6d81180bSLoGin } 404*6d81180bSLoGin return Ok(0); 405*6d81180bSLoGin } 406*6d81180bSLoGin return Err(SystemError::EBADF); 407*6d81180bSLoGin } 408*6d81180bSLoGin } 409*6d81180bSLoGin return Err(SystemError::EBADF); 410*6d81180bSLoGin } 411*6d81180bSLoGin 412*6d81180bSLoGin FcntlCommand::GetFlags => { 413*6d81180bSLoGin // Get file status flags. 414*6d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 415*6d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 416*6d81180bSLoGin if let Some(file) = &fds.fds[fd as usize] { 417*6d81180bSLoGin return Ok(file.mode().bits() as usize); 418*6d81180bSLoGin } 419*6d81180bSLoGin return Err(SystemError::EBADF); 420*6d81180bSLoGin } 421*6d81180bSLoGin } 422*6d81180bSLoGin return Err(SystemError::EBADF); 423*6d81180bSLoGin } 424*6d81180bSLoGin FcntlCommand::SetFlags => { 425*6d81180bSLoGin // Set file status flags. 426*6d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 427*6d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 428*6d81180bSLoGin if let Some(file) = &mut fds.fds[fd as usize] { 429*6d81180bSLoGin let arg = arg as u32; 430*6d81180bSLoGin let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?; 431*6d81180bSLoGin file.set_mode(mode)?; 432*6d81180bSLoGin return Ok(0); 433*6d81180bSLoGin } 434*6d81180bSLoGin return Err(SystemError::EBADF); 435*6d81180bSLoGin } 436*6d81180bSLoGin } 437*6d81180bSLoGin return Err(SystemError::EBADF); 438*6d81180bSLoGin } 439*6d81180bSLoGin _ => { 440*6d81180bSLoGin // TODO: unimplemented 441*6d81180bSLoGin // 未实现的命令,返回0,不报错。 442*6d81180bSLoGin 443*6d81180bSLoGin // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd); 444*6d81180bSLoGin return Ok(0); 445*6d81180bSLoGin } 446*6d81180bSLoGin } 447*6d81180bSLoGin } 448*6d81180bSLoGin 449*6d81180bSLoGin /// # ftruncate 450*6d81180bSLoGin /// 451*6d81180bSLoGin /// ## 描述 452*6d81180bSLoGin /// 453*6d81180bSLoGin /// 改变文件大小. 454*6d81180bSLoGin /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充. 455*6d81180bSLoGin /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小. 456*6d81180bSLoGin /// 457*6d81180bSLoGin /// ## 参数 458*6d81180bSLoGin /// 459*6d81180bSLoGin /// - `fd`:文件描述符 460*6d81180bSLoGin /// - `len`:文件大小 461*6d81180bSLoGin /// 462*6d81180bSLoGin /// ## 返回值 463*6d81180bSLoGin /// 464*6d81180bSLoGin /// 如果成功,返回0,否则返回错误码. 465*6d81180bSLoGin pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> { 466*6d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 467*6d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 468*6d81180bSLoGin if let Some(file) = &mut fds.fds[fd as usize] { 469*6d81180bSLoGin let r = file.ftruncate(len).map(|_| 0); 470*6d81180bSLoGin return r; 471*6d81180bSLoGin } 472*6d81180bSLoGin return Err(SystemError::EBADF); 473*6d81180bSLoGin } 474*6d81180bSLoGin } 475*6d81180bSLoGin return Err(SystemError::EBADF); 476*6d81180bSLoGin } 4772b771e32SGou Ngai } 478cde5492fSlogin 479cde5492fSlogin #[repr(C)] 480cde5492fSlogin #[derive(Debug, Clone, Copy)] 481cde5492fSlogin pub struct IoVec { 482cde5492fSlogin /// 缓冲区的起始地址 483cde5492fSlogin pub iov_base: *mut u8, 484cde5492fSlogin /// 缓冲区的长度 485cde5492fSlogin pub iov_len: usize, 486cde5492fSlogin } 487cde5492fSlogin 488cde5492fSlogin /// 用于存储多个来自用户空间的IoVec 489cde5492fSlogin /// 490cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 491cde5492fSlogin /// TODO:支持分散读写 492cde5492fSlogin #[derive(Debug)] 493cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>); 494cde5492fSlogin 495cde5492fSlogin impl IoVecs { 496cde5492fSlogin /// 从用户空间的IoVec中构造IoVecs 497cde5492fSlogin /// 498cde5492fSlogin /// @param iov 用户空间的IoVec 499cde5492fSlogin /// @param iovcnt 用户空间的IoVec的数量 500cde5492fSlogin /// @param readv 是否为readv系统调用 501cde5492fSlogin /// 502cde5492fSlogin /// @return 构造成功返回IoVecs,否则返回错误码 503cde5492fSlogin pub unsafe fn from_user( 504cde5492fSlogin iov: *const IoVec, 505cde5492fSlogin iovcnt: usize, 506cde5492fSlogin _readv: bool, 507cde5492fSlogin ) -> Result<Self, SystemError> { 508cde5492fSlogin // 检查iov指针所在空间是否合法 509cde5492fSlogin if !verify_area( 510cde5492fSlogin iov as usize as u64, 511cde5492fSlogin (iovcnt * core::mem::size_of::<IoVec>()) as u64, 512cde5492fSlogin ) { 513cde5492fSlogin return Err(SystemError::EFAULT); 514cde5492fSlogin } 515cde5492fSlogin 516cde5492fSlogin // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 517cde5492fSlogin let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 518cde5492fSlogin 519cde5492fSlogin let mut slices: Vec<&mut [u8]> = vec![]; 520cde5492fSlogin slices.reserve(iovs.len()); 521cde5492fSlogin 522cde5492fSlogin for iov in iovs.iter() { 523cde5492fSlogin if iov.iov_len == 0 { 524cde5492fSlogin continue; 525cde5492fSlogin } 526cde5492fSlogin 527cde5492fSlogin if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) { 528cde5492fSlogin return Err(SystemError::EFAULT); 529cde5492fSlogin } 530cde5492fSlogin 531cde5492fSlogin slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 532cde5492fSlogin } 533cde5492fSlogin 534cde5492fSlogin return Ok(Self(slices)); 535cde5492fSlogin } 536cde5492fSlogin 537cde5492fSlogin /// @brief 将IoVecs中的数据聚合到一个缓冲区中 538cde5492fSlogin /// 539cde5492fSlogin /// @return 返回聚合后的缓冲区 540cde5492fSlogin pub fn gather(&self) -> Vec<u8> { 541cde5492fSlogin let mut buf = Vec::new(); 542cde5492fSlogin for slice in self.0.iter() { 543cde5492fSlogin buf.extend_from_slice(slice); 544cde5492fSlogin } 545cde5492fSlogin return buf; 546cde5492fSlogin } 547cde5492fSlogin 548cde5492fSlogin /// @brief 将给定的数据分散写入到IoVecs中 549cde5492fSlogin pub fn scatter(&mut self, data: &[u8]) { 550cde5492fSlogin let mut data: &[u8] = data; 551cde5492fSlogin for slice in self.0.iter_mut() { 552cde5492fSlogin let len = core::cmp::min(slice.len(), data.len()); 553cde5492fSlogin if len == 0 { 554cde5492fSlogin continue; 555cde5492fSlogin } 556cde5492fSlogin 557cde5492fSlogin slice[..len].copy_from_slice(&data[..len]); 558cde5492fSlogin data = &data[len..]; 559cde5492fSlogin } 560cde5492fSlogin } 561cde5492fSlogin 562cde5492fSlogin /// @brief 创建与IoVecs等长的缓冲区 563cde5492fSlogin /// 564cde5492fSlogin /// @param set_len 是否设置返回的Vec的len。 565cde5492fSlogin /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 566cde5492fSlogin /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 567cde5492fSlogin /// 568cde5492fSlogin /// @return 返回创建的缓冲区 569cde5492fSlogin pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 570cde5492fSlogin let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 571cde5492fSlogin let mut buf: Vec<u8> = Vec::with_capacity(total_len); 572cde5492fSlogin 573cde5492fSlogin if set_len { 574cde5492fSlogin unsafe { 575cde5492fSlogin buf.set_len(total_len); 576cde5492fSlogin } 577cde5492fSlogin } 578cde5492fSlogin return buf; 579cde5492fSlogin } 580cde5492fSlogin } 581