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}, 10*67b48188Shoumkh time::TimeSpec, 11004e86ffSlogin }; 12004e86ffSlogin 13004e86ffSlogin use super::{ 14ab5c8ca4Slogin core::{do_mkdir, do_remove_dir, do_unlink_at}, 156d81180bSLoGin fcntl::{FcntlCommand, FD_CLOEXEC}, 16004e86ffSlogin file::{File, FileMode}, 17ab5c8ca4Slogin utils::rsplit_path, 18ab5c8ca4Slogin Dirent, FileType, IndexNode, ROOT_INODE, 19004e86ffSlogin }; 20004e86ffSlogin 21ab5c8ca4Slogin pub const SEEK_SET: u32 = 0; 22ab5c8ca4Slogin pub const SEEK_CUR: u32 = 1; 23ab5c8ca4Slogin pub const SEEK_END: u32 = 2; 24ab5c8ca4Slogin pub const SEEK_MAX: u32 = 3; 25004e86ffSlogin 26*67b48188Shoumkh bitflags! { 27*67b48188Shoumkh /// 文件类型和权限 28*67b48188Shoumkh pub struct ModeType: u32 { 29*67b48188Shoumkh /// 掩码 30*67b48188Shoumkh const S_IFMT = 0o0_170_000; 31*67b48188Shoumkh /// 文件类型 32*67b48188Shoumkh const S_IFSOCK = 0o140000; 33*67b48188Shoumkh const S_IFLNK = 0o120000; 34*67b48188Shoumkh const S_IFREG = 0o100000; 35*67b48188Shoumkh const S_IFBLK = 0o060000; 36*67b48188Shoumkh const S_IFDIR = 0o040000; 37*67b48188Shoumkh const S_IFCHR = 0o020000; 38*67b48188Shoumkh const S_IFIFO = 0o010000; 39*67b48188Shoumkh 40*67b48188Shoumkh const S_ISUID = 0o004000; 41*67b48188Shoumkh const S_ISGID = 0o002000; 42*67b48188Shoumkh const S_ISVTX = 0o001000; 43*67b48188Shoumkh /// 文件用户权限 44*67b48188Shoumkh const S_IRWXU = 0o0700; 45*67b48188Shoumkh const S_IRUSR = 0o0400; 46*67b48188Shoumkh const S_IWUSR = 0o0200; 47*67b48188Shoumkh const S_IXUSR = 0o0100; 48*67b48188Shoumkh /// 文件组权限 49*67b48188Shoumkh const S_IRWXG = 0o0070; 50*67b48188Shoumkh const S_IRGRP = 0o0040; 51*67b48188Shoumkh const S_IWGRP = 0o0020; 52*67b48188Shoumkh const S_IXGRP = 0o0010; 53*67b48188Shoumkh /// 文件其他用户权限 54*67b48188Shoumkh const S_IRWXO = 0o0007; 55*67b48188Shoumkh const S_IROTH = 0o0004; 56*67b48188Shoumkh const S_IWOTH = 0o0002; 57*67b48188Shoumkh const S_IXOTH = 0o0001; 58*67b48188Shoumkh } 59*67b48188Shoumkh } 60*67b48188Shoumkh 61*67b48188Shoumkh #[repr(C)] 62*67b48188Shoumkh /// # 文件信息结构体 63*67b48188Shoumkh pub struct PosixKstat { 64*67b48188Shoumkh /// 硬件设备ID 65*67b48188Shoumkh dev_id: u64, 66*67b48188Shoumkh /// inode号 67*67b48188Shoumkh inode: u64, 68*67b48188Shoumkh /// 硬链接数 69*67b48188Shoumkh nlink: u64, 70*67b48188Shoumkh /// 文件权限 71*67b48188Shoumkh mode: ModeType, 72*67b48188Shoumkh /// 所有者用户ID 73*67b48188Shoumkh uid: i32, 74*67b48188Shoumkh /// 所有者组ID 75*67b48188Shoumkh gid: i32, 76*67b48188Shoumkh /// 设备ID 77*67b48188Shoumkh rdev: i64, 78*67b48188Shoumkh /// 文件大小 79*67b48188Shoumkh size: i64, 80*67b48188Shoumkh /// 文件系统块大小 81*67b48188Shoumkh blcok_size: i64, 82*67b48188Shoumkh /// 分配的512B块数 83*67b48188Shoumkh blocks: u64, 84*67b48188Shoumkh /// 最后访问时间 85*67b48188Shoumkh atime: TimeSpec, 86*67b48188Shoumkh /// 最后修改时间 87*67b48188Shoumkh mtime: TimeSpec, 88*67b48188Shoumkh /// 最后状态变化时间 89*67b48188Shoumkh ctime: TimeSpec, 90*67b48188Shoumkh /// 用于填充结构体大小的空白数据 91*67b48188Shoumkh pub _pad: [i8; 24], 92*67b48188Shoumkh } 93*67b48188Shoumkh impl PosixKstat { 94*67b48188Shoumkh fn new() -> Self { 95*67b48188Shoumkh Self { 96*67b48188Shoumkh inode: 0, 97*67b48188Shoumkh dev_id: 0, 98*67b48188Shoumkh mode: ModeType { bits: 0 }, 99*67b48188Shoumkh nlink: 0, 100*67b48188Shoumkh uid: 0, 101*67b48188Shoumkh gid: 0, 102*67b48188Shoumkh rdev: 0, 103*67b48188Shoumkh size: 0, 104*67b48188Shoumkh atime: TimeSpec { 105*67b48188Shoumkh tv_sec: 0, 106*67b48188Shoumkh tv_nsec: 0, 107*67b48188Shoumkh }, 108*67b48188Shoumkh mtime: TimeSpec { 109*67b48188Shoumkh tv_sec: 0, 110*67b48188Shoumkh tv_nsec: 0, 111*67b48188Shoumkh }, 112*67b48188Shoumkh ctime: TimeSpec { 113*67b48188Shoumkh tv_sec: 0, 114*67b48188Shoumkh tv_nsec: 0, 115*67b48188Shoumkh }, 116*67b48188Shoumkh blcok_size: 0, 117*67b48188Shoumkh blocks: 0, 118*67b48188Shoumkh _pad: Default::default(), 119*67b48188Shoumkh } 120*67b48188Shoumkh } 121*67b48188Shoumkh } 122ab5c8ca4Slogin impl Syscall { 123ab5c8ca4Slogin /// @brief 为当前进程打开一个文件 124ab5c8ca4Slogin /// 125ab5c8ca4Slogin /// @param path 文件路径 126ab5c8ca4Slogin /// @param o_flags 打开文件的标志位 127ab5c8ca4Slogin /// 128ab5c8ca4Slogin /// @return 文件描述符编号,或者是错误码 129ab5c8ca4Slogin pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> { 1306d81180bSLoGin // kdebug!("open: path: {}, mode: {:?}", path, mode); 131ab5c8ca4Slogin // 文件名过长 132ab5c8ca4Slogin if path.len() > PAGE_4K_SIZE as usize { 133ab5c8ca4Slogin return Err(SystemError::ENAMETOOLONG); 134ab5c8ca4Slogin } 135ab5c8ca4Slogin 136ab5c8ca4Slogin let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path); 137ab5c8ca4Slogin 138ab5c8ca4Slogin let inode: Arc<dyn IndexNode> = if inode.is_err() { 139ab5c8ca4Slogin let errno = inode.unwrap_err(); 140ab5c8ca4Slogin // 文件不存在,且需要创建 141ab5c8ca4Slogin if mode.contains(FileMode::O_CREAT) 142ab5c8ca4Slogin && !mode.contains(FileMode::O_DIRECTORY) 143ab5c8ca4Slogin && errno == SystemError::ENOENT 144ab5c8ca4Slogin { 145ab5c8ca4Slogin let (filename, parent_path) = rsplit_path(path); 146ab5c8ca4Slogin // 查找父目录 147ab5c8ca4Slogin let parent_inode: Arc<dyn IndexNode> = 148ab5c8ca4Slogin ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; 149ab5c8ca4Slogin // 创建文件 150ab5c8ca4Slogin let inode: Arc<dyn IndexNode> = 151ab5c8ca4Slogin parent_inode.create(filename, FileType::File, 0o777)?; 152ab5c8ca4Slogin inode 153004e86ffSlogin } else { 154ab5c8ca4Slogin // 不需要创建文件,因此返回错误码 155ab5c8ca4Slogin return Err(errno); 156004e86ffSlogin } 157004e86ffSlogin } else { 158ab5c8ca4Slogin inode.unwrap() 159004e86ffSlogin }; 160004e86ffSlogin 161ab5c8ca4Slogin let file_type: FileType = inode.metadata()?.file_type; 162ab5c8ca4Slogin // 如果要打开的是文件夹,而目标不是文件夹 163ab5c8ca4Slogin if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir { 164ab5c8ca4Slogin return Err(SystemError::ENOTDIR); 165004e86ffSlogin } 166ab5c8ca4Slogin 167ab5c8ca4Slogin // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件 168ab5c8ca4Slogin if mode.contains(FileMode::O_TRUNC) 169ab5c8ca4Slogin && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY)) 170ab5c8ca4Slogin && file_type == FileType::File 171ab5c8ca4Slogin { 172ab5c8ca4Slogin inode.truncate(0)?; 173ab5c8ca4Slogin } 174ab5c8ca4Slogin 175ab5c8ca4Slogin // 创建文件对象 176ab5c8ca4Slogin let mut file: File = File::new(inode, mode)?; 177ab5c8ca4Slogin 178ab5c8ca4Slogin // 打开模式为“追加” 179ab5c8ca4Slogin if mode.contains(FileMode::O_APPEND) { 180ab5c8ca4Slogin file.lseek(SeekFrom::SeekEnd(0))?; 181ab5c8ca4Slogin } 182ab5c8ca4Slogin 183ab5c8ca4Slogin // 把文件对象存入pcb 1846d81180bSLoGin let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize); 1856d81180bSLoGin // kdebug!("open: fd: {:?}", r); 1866d81180bSLoGin return r; 187ab5c8ca4Slogin } 188ab5c8ca4Slogin 189ab5c8ca4Slogin /// @brief 关闭文件 190ab5c8ca4Slogin /// 191ab5c8ca4Slogin /// @param fd 文件描述符编号 192ab5c8ca4Slogin /// 193ab5c8ca4Slogin /// @return 成功返回0,失败返回错误码 194ab5c8ca4Slogin pub fn close(fd: usize) -> Result<usize, SystemError> { 1956d81180bSLoGin // kdebug!("syscall::close: fd: {}", fd); 196ab5c8ca4Slogin return current_pcb().drop_fd(fd as i32).map(|_| 0); 197ab5c8ca4Slogin } 198ab5c8ca4Slogin 199ab5c8ca4Slogin /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 200ab5c8ca4Slogin /// 201ab5c8ca4Slogin /// @param fd 文件描述符编号 202ab5c8ca4Slogin /// @param buf 输出缓冲区。 203ab5c8ca4Slogin /// 204ab5c8ca4Slogin /// @return Ok(usize) 成功读取的数据的字节数 205ab5c8ca4Slogin /// @return Err(SystemError) 读取失败,返回posix错误码 206ab5c8ca4Slogin pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 2076d81180bSLoGin // kdebug!("syscall::read: fd: {}, len={}", fd, buf.len()); 208ab5c8ca4Slogin let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 209ab5c8ca4Slogin if file.is_none() { 210ab5c8ca4Slogin return Err(SystemError::EBADF); 211ab5c8ca4Slogin } 212ab5c8ca4Slogin let file: &mut File = file.unwrap(); 213ab5c8ca4Slogin 214ab5c8ca4Slogin return file.read(buf.len(), buf); 215ab5c8ca4Slogin } 216ab5c8ca4Slogin 217ab5c8ca4Slogin /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 218ab5c8ca4Slogin /// 219ab5c8ca4Slogin /// @param fd 文件描述符编号 220ab5c8ca4Slogin /// @param buf 输入缓冲区。 221ab5c8ca4Slogin /// 222ab5c8ca4Slogin /// @return Ok(usize) 成功写入的数据的字节数 223ab5c8ca4Slogin /// @return Err(SystemError) 写入失败,返回posix错误码 224ab5c8ca4Slogin pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> { 2256d81180bSLoGin // kdebug!("syscall::write: fd: {}, len={}", fd, buf.len()); 226ab5c8ca4Slogin let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 227ab5c8ca4Slogin if file.is_none() { 228ab5c8ca4Slogin return Err(SystemError::EBADF); 229ab5c8ca4Slogin } 230ab5c8ca4Slogin let file: &mut File = file.unwrap(); 231ab5c8ca4Slogin 232ab5c8ca4Slogin return file.write(buf.len(), buf); 233ab5c8ca4Slogin } 234ab5c8ca4Slogin 235ab5c8ca4Slogin /// @brief 调整文件操作指针的位置 236ab5c8ca4Slogin /// 237ab5c8ca4Slogin /// @param fd 文件描述符编号 238ab5c8ca4Slogin /// @param seek 调整的方式 239ab5c8ca4Slogin /// 240ab5c8ca4Slogin /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量 241ab5c8ca4Slogin /// @return Err(SystemError) 调整失败,返回posix错误码 242ab5c8ca4Slogin pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> { 2436d81180bSLoGin // kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek); 244ab5c8ca4Slogin let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 245ab5c8ca4Slogin if file.is_none() { 246ab5c8ca4Slogin return Err(SystemError::EBADF); 247ab5c8ca4Slogin } 248ab5c8ca4Slogin let file: &mut File = file.unwrap(); 249ab5c8ca4Slogin return file.lseek(seek); 250004e86ffSlogin } 251004e86ffSlogin 252004e86ffSlogin /// @brief 切换工作目录 253004e86ffSlogin /// 254004e86ffSlogin /// @param dest_path 目标路径 255004e86ffSlogin /// 256004e86ffSlogin /// @return 返回码 描述 257004e86ffSlogin /// 0 | 成功 258004e86ffSlogin /// 259004e86ffSlogin /// EACCESS | 权限不足 260004e86ffSlogin /// 261004e86ffSlogin /// ELOOP | 解析path时遇到路径循环 262004e86ffSlogin /// 263004e86ffSlogin /// ENAMETOOLONG | 路径名过长 264004e86ffSlogin /// 265004e86ffSlogin /// ENOENT | 目标文件或目录不存在 266004e86ffSlogin /// 267004e86ffSlogin /// ENODIR | 检索期间发现非目录项 268004e86ffSlogin /// 269004e86ffSlogin /// ENOMEM | 系统内存不足 270004e86ffSlogin /// 271004e86ffSlogin /// EFAULT | 错误的地址 272004e86ffSlogin /// 273004e86ffSlogin /// ENAMETOOLONG | 路径过长 274ab5c8ca4Slogin pub fn chdir(dest_path: &str) -> Result<usize, SystemError> { 275ab5c8ca4Slogin // Copy path to kernel space to avoid some security issues 276ab5c8ca4Slogin let path: Box<&str> = Box::new(dest_path); 277004e86ffSlogin let inode = match ROOT_INODE().lookup(&path) { 278004e86ffSlogin Err(e) => { 279676b8ef6SMork kerror!("Change Directory Failed, Error = {:?}", e); 280ab5c8ca4Slogin return Err(SystemError::ENOENT); 281004e86ffSlogin } 282004e86ffSlogin Ok(i) => i, 283004e86ffSlogin }; 284004e86ffSlogin 285004e86ffSlogin match inode.metadata() { 286004e86ffSlogin Err(e) => { 287676b8ef6SMork kerror!("INode Get MetaData Failed, Error = {:?}", e); 288ab5c8ca4Slogin return Err(SystemError::ENOENT); 289004e86ffSlogin } 290004e86ffSlogin Ok(i) => { 291004e86ffSlogin if let FileType::Dir = i.file_type { 292ab5c8ca4Slogin return Ok(0); 293004e86ffSlogin } else { 294ab5c8ca4Slogin return Err(SystemError::ENOTDIR); 295004e86ffSlogin } 296004e86ffSlogin } 297004e86ffSlogin } 298004e86ffSlogin } 299004e86ffSlogin 300004e86ffSlogin /// @brief 获取目录中的数据 301004e86ffSlogin /// 302ab5c8ca4Slogin /// TODO: 这个函数的语义与Linux不一致,需要修改!!! 303ab5c8ca4Slogin /// 304004e86ffSlogin /// @param fd 文件描述符号 305ab5c8ca4Slogin /// @param buf 输出缓冲区 306ab5c8ca4Slogin /// 307ab5c8ca4Slogin /// @return 成功返回读取的字节数,失败返回错误码 308ab5c8ca4Slogin pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 309ab5c8ca4Slogin let dirent = 310ab5c8ca4Slogin unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?; 311004e86ffSlogin 312004e86ffSlogin if fd < 0 || fd as u32 > PROC_MAX_FD_NUM { 313ab5c8ca4Slogin return Err(SystemError::EBADF); 314004e86ffSlogin } 315004e86ffSlogin 316004e86ffSlogin // 获取fd 317004e86ffSlogin let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) { 318004e86ffSlogin None => { 319ab5c8ca4Slogin return Err(SystemError::EBADF); 320004e86ffSlogin } 321004e86ffSlogin Some(file) => file, 322004e86ffSlogin }; 323004e86ffSlogin // kdebug!("file={file:?}"); 324004e86ffSlogin 325ab5c8ca4Slogin return file.readdir(dirent).map(|x| x as usize); 326004e86ffSlogin } 327004e86ffSlogin 328004e86ffSlogin /// @brief 创建文件夹 329004e86ffSlogin /// 330004e86ffSlogin /// @param path(r8) 路径 / mode(r9) 模式 331004e86ffSlogin /// 332004e86ffSlogin /// @return uint64_t 负数错误码 / 0表示成功 333ab5c8ca4Slogin pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> { 334ab5c8ca4Slogin return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); 335004e86ffSlogin } 336004e86ffSlogin 337ab5c8ca4Slogin /// **删除文件夹、取消文件的链接、删除文件的系统调用** 338004e86ffSlogin /// 339ab5c8ca4Slogin /// ## 参数 340004e86ffSlogin /// 341ab5c8ca4Slogin /// - `dirfd`:文件夹的文件描述符.目前暂未实现 342ab5c8ca4Slogin /// - `pathname`:文件夹的路径 343ab5c8ca4Slogin /// - `flags`:标志位 344004e86ffSlogin /// 345004e86ffSlogin /// 346ab5c8ca4Slogin pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> { 347004e86ffSlogin // kdebug!("sys_unlink_at={path:?}"); 348ab5c8ca4Slogin if (flags & (!AT_REMOVEDIR)) != 0 { 349ab5c8ca4Slogin return Err(SystemError::EINVAL); 350004e86ffSlogin } 351004e86ffSlogin 352ab5c8ca4Slogin if (flags & AT_REMOVEDIR) > 0 { 353004e86ffSlogin // kdebug!("rmdir"); 354ab5c8ca4Slogin match do_remove_dir(&pathname) { 355004e86ffSlogin Err(err) => { 356676b8ef6SMork kerror!("Failed to Remove Directory, Error Code = {:?}", err); 357ab5c8ca4Slogin return Err(err); 358004e86ffSlogin } 359004e86ffSlogin Ok(_) => { 360ab5c8ca4Slogin return Ok(0); 361004e86ffSlogin } 362004e86ffSlogin } 363004e86ffSlogin } 364004e86ffSlogin 365ab5c8ca4Slogin match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) { 366004e86ffSlogin Err(err) => { 367676b8ef6SMork kerror!("Failed to Remove Directory, Error Code = {:?}", err); 368ab5c8ca4Slogin return Err(err); 369004e86ffSlogin } 370004e86ffSlogin Ok(_) => { 371ab5c8ca4Slogin return Ok(0); 372004e86ffSlogin } 373004e86ffSlogin } 374004e86ffSlogin } 3752b771e32SGou Ngai 376ab5c8ca4Slogin /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 377ab5c8ca4Slogin pub fn dup(oldfd: i32) -> Result<usize, SystemError> { 3782b771e32SGou Ngai if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 3792b771e32SGou Ngai // 获得当前文件描述符数组 3802b771e32SGou Ngai // 确认oldfd是否有效 3812b771e32SGou Ngai if FileDescriptorVec::validate_fd(oldfd) { 3822b771e32SGou Ngai if let Some(file) = &fds.fds[oldfd as usize] { 3832b771e32SGou Ngai // 尝试获取对应的文件结构体 384ab5c8ca4Slogin let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?; 385ab5c8ca4Slogin 3862b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 387ab5c8ca4Slogin let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize); 3882b771e32SGou Ngai return res; 3892b771e32SGou Ngai } 3902b771e32SGou Ngai // oldfd对应的文件不存在 3912b771e32SGou Ngai return Err(SystemError::EBADF); 3922b771e32SGou Ngai } 3932b771e32SGou Ngai return Err(SystemError::EBADF); 3942b771e32SGou Ngai } else { 3952b771e32SGou Ngai return Err(SystemError::EMFILE); 3962b771e32SGou Ngai } 3972b771e32SGou Ngai } 3982b771e32SGou Ngai 399ab5c8ca4Slogin /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 400ab5c8ca4Slogin /// 并返回新复制的文件结构体对应的fd. 401ab5c8ca4Slogin /// 如果新fd已经打开,则会先关闭新fd. 402ab5c8ca4Slogin /// 403ab5c8ca4Slogin /// ## 参数 404ab5c8ca4Slogin /// 405ab5c8ca4Slogin /// - `oldfd`:旧文件描述符 406ab5c8ca4Slogin /// - `newfd`:新文件描述符 407ab5c8ca4Slogin /// 408ab5c8ca4Slogin /// ## 返回值 409ab5c8ca4Slogin /// 410ab5c8ca4Slogin /// - 成功:新文件描述符 411ab5c8ca4Slogin /// - 失败:错误码 412ab5c8ca4Slogin pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> { 4132b771e32SGou Ngai if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 4142b771e32SGou Ngai // 获得当前文件描述符数组 4152b771e32SGou Ngai if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) { 4162b771e32SGou Ngai //确认oldfd, newid是否有效 4172b771e32SGou Ngai if oldfd == newfd { 4182b771e32SGou Ngai // 若oldfd与newfd相等 419ab5c8ca4Slogin return Ok(newfd as usize); 4202b771e32SGou Ngai } 4212b771e32SGou Ngai 4222b771e32SGou Ngai if let Some(file) = &fds.fds[oldfd as usize] { 4232b771e32SGou Ngai if fds.fds[newfd as usize].is_some() { 4242b771e32SGou Ngai // close newfd 4252b771e32SGou Ngai if let Err(_) = current_pcb().drop_fd(newfd) { 4262b771e32SGou Ngai // An I/O error occurred while attempting to close fildes2. 4272b771e32SGou Ngai return Err(SystemError::EIO); 4282b771e32SGou Ngai } 4292b771e32SGou Ngai } 4302b771e32SGou Ngai 4312b771e32SGou Ngai // 尝试获取对应的文件结构体 4322b771e32SGou Ngai let file_cp = file.try_clone(); 4332b771e32SGou Ngai if file_cp.is_none() { 4342b771e32SGou Ngai return Err(SystemError::EBADF); 4352b771e32SGou Ngai } 4362b771e32SGou Ngai // 申请文件描述符,并把文件对象存入其中 437ab5c8ca4Slogin let res = current_pcb() 438ab5c8ca4Slogin .alloc_fd(*file_cp.unwrap(), Some(newfd)) 439ab5c8ca4Slogin .map(|x| x as usize); 4402b771e32SGou Ngai 4412b771e32SGou Ngai return res; 4422b771e32SGou Ngai } 4432b771e32SGou Ngai return Err(SystemError::EBADF); 4442b771e32SGou Ngai } else { 4452b771e32SGou Ngai return Err(SystemError::EBADF); 4462b771e32SGou Ngai } 4472b771e32SGou Ngai } 4482b771e32SGou Ngai // 从pcb获取文件描述符数组失败 4492b771e32SGou Ngai return Err(SystemError::EMFILE); 4502b771e32SGou Ngai } 4516d81180bSLoGin 4526d81180bSLoGin /// # fcntl 4536d81180bSLoGin /// 4546d81180bSLoGin /// ## 参数 4556d81180bSLoGin /// 4566d81180bSLoGin /// - `fd`:文件描述符 4576d81180bSLoGin /// - `cmd`:命令 4586d81180bSLoGin /// - `arg`:参数 4596d81180bSLoGin pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> { 4606d81180bSLoGin match cmd { 4616d81180bSLoGin FcntlCommand::DupFd => { 4626d81180bSLoGin if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD { 4636d81180bSLoGin return Err(SystemError::EBADF); 4646d81180bSLoGin } 4656d81180bSLoGin let arg = arg as usize; 4666d81180bSLoGin for i in arg..FileDescriptorVec::PROCESS_MAX_FD { 4676d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 4686d81180bSLoGin if fds.fds[i as usize].is_none() { 4696d81180bSLoGin return Self::dup2(fd, i as i32); 4706d81180bSLoGin } 4716d81180bSLoGin } 4726d81180bSLoGin } 4736d81180bSLoGin return Err(SystemError::EMFILE); 4746d81180bSLoGin } 4756d81180bSLoGin FcntlCommand::GetFd => { 4766d81180bSLoGin // Get file descriptor flags. 4776d81180bSLoGin 4786d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 4796d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 4806d81180bSLoGin if let Some(file) = &fds.fds[fd as usize] { 4816d81180bSLoGin if file.close_on_exec() { 4826d81180bSLoGin return Ok(FD_CLOEXEC as usize); 4836d81180bSLoGin } 4846d81180bSLoGin } 4856d81180bSLoGin return Err(SystemError::EBADF); 4866d81180bSLoGin } 4876d81180bSLoGin } 4886d81180bSLoGin return Err(SystemError::EBADF); 4896d81180bSLoGin } 4906d81180bSLoGin FcntlCommand::SetFd => { 4916d81180bSLoGin // Set file descriptor flags. 4926d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 4936d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 4946d81180bSLoGin if let Some(file) = &mut fds.fds[fd as usize] { 4956d81180bSLoGin let arg = arg as u32; 4966d81180bSLoGin if arg & FD_CLOEXEC != 0 { 4976d81180bSLoGin file.set_close_on_exec(true); 4986d81180bSLoGin } else { 4996d81180bSLoGin file.set_close_on_exec(false); 5006d81180bSLoGin } 5016d81180bSLoGin return Ok(0); 5026d81180bSLoGin } 5036d81180bSLoGin return Err(SystemError::EBADF); 5046d81180bSLoGin } 5056d81180bSLoGin } 5066d81180bSLoGin return Err(SystemError::EBADF); 5076d81180bSLoGin } 5086d81180bSLoGin 5096d81180bSLoGin FcntlCommand::GetFlags => { 5106d81180bSLoGin // Get file status flags. 5116d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 5126d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 5136d81180bSLoGin if let Some(file) = &fds.fds[fd as usize] { 5146d81180bSLoGin return Ok(file.mode().bits() as usize); 5156d81180bSLoGin } 5166d81180bSLoGin return Err(SystemError::EBADF); 5176d81180bSLoGin } 5186d81180bSLoGin } 5196d81180bSLoGin return Err(SystemError::EBADF); 5206d81180bSLoGin } 5216d81180bSLoGin FcntlCommand::SetFlags => { 5226d81180bSLoGin // Set file status flags. 5236d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 5246d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 5256d81180bSLoGin if let Some(file) = &mut fds.fds[fd as usize] { 5266d81180bSLoGin let arg = arg as u32; 5276d81180bSLoGin let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?; 5286d81180bSLoGin file.set_mode(mode)?; 5296d81180bSLoGin return Ok(0); 5306d81180bSLoGin } 5316d81180bSLoGin return Err(SystemError::EBADF); 5326d81180bSLoGin } 5336d81180bSLoGin } 5346d81180bSLoGin return Err(SystemError::EBADF); 5356d81180bSLoGin } 5366d81180bSLoGin _ => { 5376d81180bSLoGin // TODO: unimplemented 5386d81180bSLoGin // 未实现的命令,返回0,不报错。 5396d81180bSLoGin 5406d81180bSLoGin // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd); 5416d81180bSLoGin return Ok(0); 5426d81180bSLoGin } 5436d81180bSLoGin } 5446d81180bSLoGin } 5456d81180bSLoGin 5466d81180bSLoGin /// # ftruncate 5476d81180bSLoGin /// 5486d81180bSLoGin /// ## 描述 5496d81180bSLoGin /// 5506d81180bSLoGin /// 改变文件大小. 5516d81180bSLoGin /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充. 5526d81180bSLoGin /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小. 5536d81180bSLoGin /// 5546d81180bSLoGin /// ## 参数 5556d81180bSLoGin /// 5566d81180bSLoGin /// - `fd`:文件描述符 5576d81180bSLoGin /// - `len`:文件大小 5586d81180bSLoGin /// 5596d81180bSLoGin /// ## 返回值 5606d81180bSLoGin /// 5616d81180bSLoGin /// 如果成功,返回0,否则返回错误码. 5626d81180bSLoGin pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> { 5636d81180bSLoGin if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 5646d81180bSLoGin if FileDescriptorVec::validate_fd(fd) { 5656d81180bSLoGin if let Some(file) = &mut fds.fds[fd as usize] { 5666d81180bSLoGin let r = file.ftruncate(len).map(|_| 0); 5676d81180bSLoGin return r; 5686d81180bSLoGin } 5696d81180bSLoGin return Err(SystemError::EBADF); 5706d81180bSLoGin } 5716d81180bSLoGin } 5726d81180bSLoGin return Err(SystemError::EBADF); 5736d81180bSLoGin } 574*67b48188Shoumkh fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> { 575*67b48188Shoumkh let cur = current_pcb(); 576*67b48188Shoumkh match cur.get_file_ref_by_fd(fd) { 577*67b48188Shoumkh Some(file) => { 578*67b48188Shoumkh let mut kstat = PosixKstat::new(); 579*67b48188Shoumkh // 获取文件信息 580*67b48188Shoumkh match file.metadata() { 581*67b48188Shoumkh Ok(metadata) => { 582*67b48188Shoumkh kstat.size = metadata.size as i64; 583*67b48188Shoumkh kstat.dev_id = metadata.dev_id as u64; 584*67b48188Shoumkh kstat.inode = metadata.inode_id as u64; 585*67b48188Shoumkh kstat.blcok_size = metadata.blk_size as i64; 586*67b48188Shoumkh kstat.blocks = metadata.blocks as u64; 587*67b48188Shoumkh 588*67b48188Shoumkh kstat.atime.tv_sec = metadata.atime.tv_sec; 589*67b48188Shoumkh kstat.atime.tv_nsec = metadata.atime.tv_nsec; 590*67b48188Shoumkh kstat.mtime.tv_sec = metadata.mtime.tv_sec; 591*67b48188Shoumkh kstat.mtime.tv_nsec = metadata.mtime.tv_nsec; 592*67b48188Shoumkh kstat.ctime.tv_sec = metadata.ctime.tv_sec; 593*67b48188Shoumkh kstat.ctime.tv_nsec = metadata.ctime.tv_nsec; 594*67b48188Shoumkh 595*67b48188Shoumkh kstat.nlink = metadata.nlinks as u64; 596*67b48188Shoumkh kstat.uid = metadata.uid as i32; 597*67b48188Shoumkh kstat.gid = metadata.gid as i32; 598*67b48188Shoumkh kstat.rdev = metadata.raw_dev as i64; 599*67b48188Shoumkh kstat.mode.bits = metadata.mode; 600*67b48188Shoumkh match file.file_type() { 601*67b48188Shoumkh FileType::File => kstat.mode.insert(ModeType::S_IFMT), 602*67b48188Shoumkh FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR), 603*67b48188Shoumkh FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK), 604*67b48188Shoumkh FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR), 605*67b48188Shoumkh FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK), 606*67b48188Shoumkh FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK), 607*67b48188Shoumkh FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO), 608*67b48188Shoumkh } 609*67b48188Shoumkh } 610*67b48188Shoumkh Err(e) => return Err(e), 611*67b48188Shoumkh } 612*67b48188Shoumkh 613*67b48188Shoumkh return Ok(kstat); 614*67b48188Shoumkh } 615*67b48188Shoumkh None => { 616*67b48188Shoumkh return Err(SystemError::EINVAL); 617*67b48188Shoumkh } 618*67b48188Shoumkh } 619*67b48188Shoumkh } 620*67b48188Shoumkh pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 621*67b48188Shoumkh match Self::do_fstat(fd) { 622*67b48188Shoumkh Ok(kstat) => { 623*67b48188Shoumkh if usr_kstat.is_null() { 624*67b48188Shoumkh return Err(SystemError::EFAULT); 625*67b48188Shoumkh } 626*67b48188Shoumkh unsafe { 627*67b48188Shoumkh *usr_kstat = kstat; 628*67b48188Shoumkh } 629*67b48188Shoumkh return Ok(0); 630*67b48188Shoumkh } 631*67b48188Shoumkh Err(e) => return Err(e), 632*67b48188Shoumkh } 633*67b48188Shoumkh } 6342b771e32SGou Ngai } 635cde5492fSlogin 636cde5492fSlogin #[repr(C)] 637cde5492fSlogin #[derive(Debug, Clone, Copy)] 638cde5492fSlogin pub struct IoVec { 639cde5492fSlogin /// 缓冲区的起始地址 640cde5492fSlogin pub iov_base: *mut u8, 641cde5492fSlogin /// 缓冲区的长度 642cde5492fSlogin pub iov_len: usize, 643cde5492fSlogin } 644cde5492fSlogin 645cde5492fSlogin /// 用于存储多个来自用户空间的IoVec 646cde5492fSlogin /// 647cde5492fSlogin /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 648cde5492fSlogin /// TODO:支持分散读写 649cde5492fSlogin #[derive(Debug)] 650cde5492fSlogin pub struct IoVecs(Vec<&'static mut [u8]>); 651cde5492fSlogin 652cde5492fSlogin impl IoVecs { 653cde5492fSlogin /// 从用户空间的IoVec中构造IoVecs 654cde5492fSlogin /// 655cde5492fSlogin /// @param iov 用户空间的IoVec 656cde5492fSlogin /// @param iovcnt 用户空间的IoVec的数量 657cde5492fSlogin /// @param readv 是否为readv系统调用 658cde5492fSlogin /// 659cde5492fSlogin /// @return 构造成功返回IoVecs,否则返回错误码 660cde5492fSlogin pub unsafe fn from_user( 661cde5492fSlogin iov: *const IoVec, 662cde5492fSlogin iovcnt: usize, 663cde5492fSlogin _readv: bool, 664cde5492fSlogin ) -> Result<Self, SystemError> { 665cde5492fSlogin // 检查iov指针所在空间是否合法 666cde5492fSlogin if !verify_area( 667cde5492fSlogin iov as usize as u64, 668cde5492fSlogin (iovcnt * core::mem::size_of::<IoVec>()) as u64, 669cde5492fSlogin ) { 670cde5492fSlogin return Err(SystemError::EFAULT); 671cde5492fSlogin } 672cde5492fSlogin 673cde5492fSlogin // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 674cde5492fSlogin let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 675cde5492fSlogin 676cde5492fSlogin let mut slices: Vec<&mut [u8]> = vec![]; 677cde5492fSlogin slices.reserve(iovs.len()); 678cde5492fSlogin 679cde5492fSlogin for iov in iovs.iter() { 680cde5492fSlogin if iov.iov_len == 0 { 681cde5492fSlogin continue; 682cde5492fSlogin } 683cde5492fSlogin 684cde5492fSlogin if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) { 685cde5492fSlogin return Err(SystemError::EFAULT); 686cde5492fSlogin } 687cde5492fSlogin 688cde5492fSlogin slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 689cde5492fSlogin } 690cde5492fSlogin 691cde5492fSlogin return Ok(Self(slices)); 692cde5492fSlogin } 693cde5492fSlogin 694cde5492fSlogin /// @brief 将IoVecs中的数据聚合到一个缓冲区中 695cde5492fSlogin /// 696cde5492fSlogin /// @return 返回聚合后的缓冲区 697cde5492fSlogin pub fn gather(&self) -> Vec<u8> { 698cde5492fSlogin let mut buf = Vec::new(); 699cde5492fSlogin for slice in self.0.iter() { 700cde5492fSlogin buf.extend_from_slice(slice); 701cde5492fSlogin } 702cde5492fSlogin return buf; 703cde5492fSlogin } 704cde5492fSlogin 705cde5492fSlogin /// @brief 将给定的数据分散写入到IoVecs中 706cde5492fSlogin pub fn scatter(&mut self, data: &[u8]) { 707cde5492fSlogin let mut data: &[u8] = data; 708cde5492fSlogin for slice in self.0.iter_mut() { 709cde5492fSlogin let len = core::cmp::min(slice.len(), data.len()); 710cde5492fSlogin if len == 0 { 711cde5492fSlogin continue; 712cde5492fSlogin } 713cde5492fSlogin 714cde5492fSlogin slice[..len].copy_from_slice(&data[..len]); 715cde5492fSlogin data = &data[len..]; 716cde5492fSlogin } 717cde5492fSlogin } 718cde5492fSlogin 719cde5492fSlogin /// @brief 创建与IoVecs等长的缓冲区 720cde5492fSlogin /// 721cde5492fSlogin /// @param set_len 是否设置返回的Vec的len。 722cde5492fSlogin /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 723cde5492fSlogin /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 724cde5492fSlogin /// 725cde5492fSlogin /// @return 返回创建的缓冲区 726cde5492fSlogin pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 727cde5492fSlogin let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 728cde5492fSlogin let mut buf: Vec<u8> = Vec::with_capacity(total_len); 729cde5492fSlogin 730cde5492fSlogin if set_len { 731cde5492fSlogin unsafe { 732cde5492fSlogin buf.set_len(total_len); 733cde5492fSlogin } 734cde5492fSlogin } 735cde5492fSlogin return buf; 736cde5492fSlogin } 737cde5492fSlogin } 738