1 use core::ffi::CStr; 2 3 use alloc::{ 4 string::{String, ToString}, 5 sync::Arc, 6 vec::Vec, 7 }; 8 9 use crate::{ 10 driver::base::{block::SeekFrom, device::DeviceNumber}, 11 filesystem::vfs::file::FileDescriptorVec, 12 kerror, 13 libs::rwlock::RwLockWriteGuard, 14 mm::{verify_area, VirtAddr}, 15 process::ProcessManager, 16 syscall::{ 17 user_access::{check_and_clone_cstr, UserBufferReader, UserBufferWriter}, 18 Syscall, SystemError, 19 }, 20 time::TimeSpec, 21 }; 22 23 use super::{ 24 core::{do_mkdir, do_remove_dir, do_unlink_at}, 25 fcntl::{AtFlags, FcntlCommand, FD_CLOEXEC}, 26 file::{File, FileMode}, 27 open::{do_faccessat, do_fchmodat, do_sys_open}, 28 utils::{rsplit_path, user_path_at}, 29 Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES, 30 }; 31 // use crate::kdebug; 32 33 pub const SEEK_SET: u32 = 0; 34 pub const SEEK_CUR: u32 = 1; 35 pub const SEEK_END: u32 = 2; 36 pub const SEEK_MAX: u32 = 3; 37 38 bitflags! { 39 /// 文件类型和权限 40 #[repr(C)] 41 pub struct ModeType: u32 { 42 /// 掩码 43 const S_IFMT = 0o0_170_000; 44 /// 文件类型 45 const S_IFSOCK = 0o140000; 46 const S_IFLNK = 0o120000; 47 const S_IFREG = 0o100000; 48 const S_IFBLK = 0o060000; 49 const S_IFDIR = 0o040000; 50 const S_IFCHR = 0o020000; 51 const S_IFIFO = 0o010000; 52 53 const S_ISUID = 0o004000; 54 const S_ISGID = 0o002000; 55 const S_ISVTX = 0o001000; 56 /// 文件用户权限 57 const S_IRWXU = 0o0700; 58 const S_IRUSR = 0o0400; 59 const S_IWUSR = 0o0200; 60 const S_IXUSR = 0o0100; 61 /// 文件组权限 62 const S_IRWXG = 0o0070; 63 const S_IRGRP = 0o0040; 64 const S_IWGRP = 0o0020; 65 const S_IXGRP = 0o0010; 66 /// 文件其他用户权限 67 const S_IRWXO = 0o0007; 68 const S_IROTH = 0o0004; 69 const S_IWOTH = 0o0002; 70 const S_IXOTH = 0o0001; 71 72 /// 0o777 73 const S_IRWXUGO = Self::S_IRWXU.bits | Self::S_IRWXG.bits | Self::S_IRWXO.bits; 74 /// 0o7777 75 const S_IALLUGO = Self::S_ISUID.bits | Self::S_ISGID.bits | Self::S_ISVTX.bits| Self::S_IRWXUGO.bits; 76 /// 0o444 77 const S_IRUGO = Self::S_IRUSR.bits | Self::S_IRGRP.bits | Self::S_IROTH.bits; 78 /// 0o222 79 const S_IWUGO = Self::S_IWUSR.bits | Self::S_IWGRP.bits | Self::S_IWOTH.bits; 80 /// 0o111 81 const S_IXUGO = Self::S_IXUSR.bits | Self::S_IXGRP.bits | Self::S_IXOTH.bits; 82 83 84 } 85 } 86 87 #[repr(C)] 88 /// # 文件信息结构体 89 pub struct PosixKstat { 90 /// 硬件设备ID 91 dev_id: u64, 92 /// inode号 93 inode: u64, 94 /// 硬链接数 95 nlink: u64, 96 /// 文件权限 97 mode: ModeType, 98 /// 所有者用户ID 99 uid: i32, 100 /// 所有者组ID 101 gid: i32, 102 /// 设备ID 103 rdev: i64, 104 /// 文件大小 105 size: i64, 106 /// 文件系统块大小 107 blcok_size: i64, 108 /// 分配的512B块数 109 blocks: u64, 110 /// 最后访问时间 111 atime: TimeSpec, 112 /// 最后修改时间 113 mtime: TimeSpec, 114 /// 最后状态变化时间 115 ctime: TimeSpec, 116 /// 用于填充结构体大小的空白数据 117 pub _pad: [i8; 24], 118 } 119 impl PosixKstat { 120 fn new() -> Self { 121 Self { 122 inode: 0, 123 dev_id: 0, 124 mode: ModeType { bits: 0 }, 125 nlink: 0, 126 uid: 0, 127 gid: 0, 128 rdev: 0, 129 size: 0, 130 atime: TimeSpec { 131 tv_sec: 0, 132 tv_nsec: 0, 133 }, 134 mtime: TimeSpec { 135 tv_sec: 0, 136 tv_nsec: 0, 137 }, 138 ctime: TimeSpec { 139 tv_sec: 0, 140 tv_nsec: 0, 141 }, 142 blcok_size: 0, 143 blocks: 0, 144 _pad: Default::default(), 145 } 146 } 147 } 148 149 /// 150 /// Arguments for how openat2(2) should open the target path. If only @flags and 151 /// @mode are non-zero, then openat2(2) operates very similarly to openat(2). 152 /// 153 /// However, unlike openat(2), unknown or invalid bits in @flags result in 154 /// -EINVAL rather than being silently ignored. @mode must be zero unless one of 155 /// {O_CREAT, O_TMPFILE} are set. 156 /// 157 /// ## 成员变量 158 /// 159 /// - flags: O_* flags. 160 /// - mode: O_CREAT/O_TMPFILE file mode. 161 /// - resolve: RESOLVE_* flags. 162 #[derive(Debug, Clone, Copy)] 163 #[repr(C)] 164 pub struct PosixOpenHow { 165 pub flags: u64, 166 pub mode: u64, 167 pub resolve: u64, 168 } 169 170 impl PosixOpenHow { 171 #[allow(dead_code)] 172 pub fn new(flags: u64, mode: u64, resolve: u64) -> Self { 173 Self { 174 flags, 175 mode, 176 resolve, 177 } 178 } 179 } 180 181 #[derive(Debug, Clone, Copy)] 182 pub struct OpenHow { 183 pub o_flags: FileMode, 184 pub mode: ModeType, 185 pub resolve: OpenHowResolve, 186 } 187 188 impl OpenHow { 189 pub fn new(mut o_flags: FileMode, mut mode: ModeType, resolve: OpenHowResolve) -> Self { 190 if !o_flags.contains(FileMode::O_CREAT) { 191 mode = ModeType::empty(); 192 } 193 194 if o_flags.contains(FileMode::O_PATH) { 195 o_flags = o_flags.intersection(FileMode::O_PATH_FLAGS); 196 } 197 198 Self { 199 o_flags, 200 mode, 201 resolve, 202 } 203 } 204 } 205 206 impl From<PosixOpenHow> for OpenHow { 207 fn from(posix_open_how: PosixOpenHow) -> Self { 208 let o_flags = FileMode::from_bits_truncate(posix_open_how.flags as u32); 209 let mode = ModeType::from_bits_truncate(posix_open_how.mode as u32); 210 let resolve = OpenHowResolve::from_bits_truncate(posix_open_how.resolve as u64); 211 return Self::new(o_flags, mode, resolve); 212 } 213 } 214 215 bitflags! { 216 pub struct OpenHowResolve: u64{ 217 /// Block mount-point crossings 218 /// (including bind-mounts). 219 const RESOLVE_NO_XDEV = 0x01; 220 221 /// Block traversal through procfs-style 222 /// "magic-links" 223 const RESOLVE_NO_MAGICLINKS = 0x02; 224 225 /// Block traversal through all symlinks 226 /// (implies OEXT_NO_MAGICLINKS) 227 const RESOLVE_NO_SYMLINKS = 0x04; 228 /// Block "lexical" trickery like 229 /// "..", symlinks, and absolute 230 const RESOLVE_BENEATH = 0x08; 231 /// Make all jumps to "/" and ".." 232 /// be scoped inside the dirfd 233 /// (similar to chroot(2)). 234 const RESOLVE_IN_ROOT = 0x10; 235 // Only complete if resolution can be 236 // completed through cached lookup. May 237 // return -EAGAIN if that's not 238 // possible. 239 const RESOLVE_CACHED = 0x20; 240 } 241 } 242 impl Syscall { 243 /// @brief 为当前进程打开一个文件 244 /// 245 /// @param path 文件路径 246 /// @param o_flags 打开文件的标志位 247 /// 248 /// @return 文件描述符编号,或者是错误码 249 pub fn open( 250 path: &str, 251 flags: FileMode, 252 mode: ModeType, 253 follow_symlink: bool, 254 ) -> Result<usize, SystemError> { 255 return do_sys_open(AtFlags::AT_FDCWD.bits(), path, flags, mode, follow_symlink); 256 } 257 258 pub fn openat( 259 dirfd: i32, 260 path: &str, 261 o_flags: FileMode, 262 mode: ModeType, 263 follow_symlink: bool, 264 ) -> Result<usize, SystemError> { 265 return do_sys_open(dirfd, path, o_flags, mode, follow_symlink); 266 } 267 268 /// @brief 关闭文件 269 /// 270 /// @param fd 文件描述符编号 271 /// 272 /// @return 成功返回0,失败返回错误码 273 pub fn close(fd: usize) -> Result<usize, SystemError> { 274 let binding = ProcessManager::current_pcb().fd_table(); 275 let mut fd_table_guard = binding.write(); 276 277 let res = fd_table_guard.drop_fd(fd as i32).map(|_| 0); 278 279 return res; 280 } 281 282 /// @brief 发送命令到文件描述符对应的设备, 283 /// 284 /// @param fd 文件描述符编号 285 /// @param cmd 设备相关的请求类型 286 /// 287 /// @return Ok(usize) 成功返回0 288 /// @return Err(SystemError) 读取失败,返回posix错误码 289 pub fn ioctl(fd: usize, cmd: u32, data: usize) -> Result<usize, SystemError> { 290 let binding = ProcessManager::current_pcb().fd_table(); 291 let fd_table_guard = binding.read(); 292 293 let file = fd_table_guard 294 .get_file_by_fd(fd as i32) 295 .ok_or(SystemError::EBADF)?; 296 297 // drop guard 以避免无法调度的问题 298 drop(fd_table_guard); 299 let r = file.lock_no_preempt().inode().ioctl(cmd, data); 300 return r; 301 } 302 303 /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 304 /// 305 /// @param fd 文件描述符编号 306 /// @param buf 输出缓冲区。 307 /// 308 /// @return Ok(usize) 成功读取的数据的字节数 309 /// @return Err(SystemError) 读取失败,返回posix错误码 310 pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 311 let binding = ProcessManager::current_pcb().fd_table(); 312 let fd_table_guard = binding.read(); 313 314 let file = fd_table_guard.get_file_by_fd(fd); 315 if file.is_none() { 316 return Err(SystemError::EBADF); 317 } 318 // drop guard 以避免无法调度的问题 319 drop(fd_table_guard); 320 let file = file.unwrap(); 321 322 return file.lock_no_preempt().read(buf.len(), buf); 323 } 324 325 /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 326 /// 327 /// @param fd 文件描述符编号 328 /// @param buf 输入缓冲区。 329 /// 330 /// @return Ok(usize) 成功写入的数据的字节数 331 /// @return Err(SystemError) 写入失败,返回posix错误码 332 pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> { 333 let binding = ProcessManager::current_pcb().fd_table(); 334 let fd_table_guard = binding.read(); 335 336 let file = fd_table_guard 337 .get_file_by_fd(fd) 338 .ok_or(SystemError::EBADF)?; 339 340 // drop guard 以避免无法调度的问题 341 drop(fd_table_guard); 342 return file.lock_no_preempt().write(buf.len(), buf); 343 } 344 345 /// @brief 调整文件操作指针的位置 346 /// 347 /// @param fd 文件描述符编号 348 /// @param seek 调整的方式 349 /// 350 /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量 351 /// @return Err(SystemError) 调整失败,返回posix错误码 352 pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> { 353 let binding = ProcessManager::current_pcb().fd_table(); 354 let fd_table_guard = binding.read(); 355 let file = fd_table_guard 356 .get_file_by_fd(fd) 357 .ok_or(SystemError::EBADF)?; 358 359 // drop guard 以避免无法调度的问题 360 drop(fd_table_guard); 361 return file.lock_no_preempt().lseek(seek); 362 } 363 364 /// @brief 切换工作目录 365 /// 366 /// @param dest_path 目标路径 367 /// 368 /// @return 返回码 描述 369 /// 0 | 成功 370 /// 371 /// EACCESS | 权限不足 372 /// 373 /// ELOOP | 解析path时遇到路径循环 374 /// 375 /// ENAMETOOLONG | 路径名过长 376 /// 377 /// ENOENT | 目标文件或目录不存在 378 /// 379 /// ENODIR | 检索期间发现非目录项 380 /// 381 /// ENOMEM | 系统内存不足 382 /// 383 /// EFAULT | 错误的地址 384 /// 385 /// ENAMETOOLONG | 路径过长 386 pub fn chdir(dest_path: &str) -> Result<usize, SystemError> { 387 let proc = ProcessManager::current_pcb(); 388 // Copy path to kernel space to avoid some security issues 389 let path = dest_path.to_string(); 390 let mut new_path = String::from(""); 391 if path.len() > 0 { 392 let cwd = match path.as_bytes()[0] { 393 b'/' => String::from("/"), 394 _ => proc.basic().cwd(), 395 }; 396 let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect(); 397 let path_split = path.split("/").filter(|&x| x != ""); 398 for seg in path_split { 399 if seg == ".." { 400 cwd_vec.pop(); 401 } else if seg == "." { 402 // 当前目录 403 } else { 404 cwd_vec.push(seg); 405 } 406 } 407 //proc.basic().set_path(String::from("")); 408 for seg in cwd_vec { 409 new_path.push_str("/"); 410 new_path.push_str(seg); 411 } 412 if new_path == "" { 413 new_path = String::from("/"); 414 } 415 } 416 let inode = 417 match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) { 418 Err(e) => { 419 kerror!("Change Directory Failed, Error = {:?}", e); 420 return Err(SystemError::ENOENT); 421 } 422 Ok(i) => i, 423 }; 424 let metadata = inode.metadata()?; 425 if metadata.file_type == FileType::Dir { 426 proc.basic_mut().set_cwd(String::from(new_path)); 427 return Ok(0); 428 } else { 429 return Err(SystemError::ENOTDIR); 430 } 431 } 432 433 /// @brief 获取当前进程的工作目录路径 434 /// 435 /// @param buf 指向缓冲区的指针 436 /// @param size 缓冲区的大小 437 /// 438 /// @return 成功,返回的指针指向包含工作目录路径的字符串 439 /// @return 错误,没有足够的空间 440 pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> { 441 let proc = ProcessManager::current_pcb(); 442 let cwd = proc.basic().cwd(); 443 444 let cwd_bytes = cwd.as_bytes(); 445 let cwd_len = cwd_bytes.len(); 446 if cwd_len + 1 > buf.len() { 447 return Err(SystemError::ENOMEM); 448 } 449 buf[..cwd_len].copy_from_slice(cwd_bytes); 450 buf[cwd_len] = 0; 451 452 return Ok(VirtAddr::new(buf.as_ptr() as usize)); 453 } 454 455 /// @brief 获取目录中的数据 456 /// 457 /// TODO: 这个函数的语义与Linux不一致,需要修改!!! 458 /// 459 /// @param fd 文件描述符号 460 /// @param buf 输出缓冲区 461 /// 462 /// @return 成功返回读取的字节数,失败返回错误码 463 pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 464 let dirent = 465 unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?; 466 467 if fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD { 468 return Err(SystemError::EBADF); 469 } 470 471 // 获取fd 472 let binding = ProcessManager::current_pcb().fd_table(); 473 let fd_table_guard = binding.read(); 474 let file = fd_table_guard 475 .get_file_by_fd(fd) 476 .ok_or(SystemError::EBADF)?; 477 478 // drop guard 以避免无法调度的问题 479 drop(fd_table_guard); 480 481 let res = file.lock_no_preempt().readdir(dirent).map(|x| x as usize); 482 483 return res; 484 } 485 486 /// @brief 创建文件夹 487 /// 488 /// @param path(r8) 路径 / mode(r9) 模式 489 /// 490 /// @return uint64_t 负数错误码 / 0表示成功 491 pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> { 492 return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); 493 } 494 495 /// **删除文件夹、取消文件的链接、删除文件的系统调用** 496 /// 497 /// ## 参数 498 /// 499 /// - `dirfd`:文件夹的文件描述符.目前暂未实现 500 /// - `pathname`:文件夹的路径 501 /// - `flags`:标志位 502 /// 503 /// 504 pub fn unlinkat(dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> { 505 let flags = AtFlags::from_bits(flags as i32).ok_or(SystemError::EINVAL)?; 506 507 if flags.contains(AtFlags::AT_REMOVEDIR) { 508 // kdebug!("rmdir"); 509 match do_remove_dir(dirfd, &pathname) { 510 Err(err) => { 511 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 512 return Err(err); 513 } 514 Ok(_) => { 515 return Ok(0); 516 } 517 } 518 } 519 520 match do_unlink_at(dirfd, &pathname) { 521 Err(err) => { 522 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 523 return Err(err); 524 } 525 Ok(_) => { 526 return Ok(0); 527 } 528 } 529 } 530 531 pub fn unlink(pathname: *const u8) -> Result<usize, SystemError> { 532 if pathname.is_null() { 533 return Err(SystemError::EFAULT); 534 } 535 let ureader = UserBufferReader::new(pathname, MAX_PATHLEN, true)?; 536 537 let buf: &[u8] = ureader.buffer(0).unwrap(); 538 539 let pathname: &CStr = CStr::from_bytes_until_nul(buf).map_err(|_| SystemError::EINVAL)?; 540 541 let pathname: &str = pathname.to_str().map_err(|_| SystemError::EINVAL)?; 542 if pathname.len() >= MAX_PATHLEN { 543 return Err(SystemError::ENAMETOOLONG); 544 } 545 let pathname = pathname.trim(); 546 547 return do_unlink_at(AtFlags::AT_FDCWD.bits(), pathname).map(|v| v as usize); 548 } 549 550 /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 551 pub fn dup(oldfd: i32) -> Result<usize, SystemError> { 552 let binding = ProcessManager::current_pcb().fd_table(); 553 let mut fd_table_guard = binding.write(); 554 555 let old_file = fd_table_guard 556 .get_file_by_fd(oldfd) 557 .ok_or(SystemError::EBADF)?; 558 559 let new_file = old_file 560 .lock_no_preempt() 561 .try_clone() 562 .ok_or(SystemError::EBADF)?; 563 // 申请文件描述符,并把文件对象存入其中 564 let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize); 565 return res; 566 } 567 568 /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 569 /// 并返回新复制的文件结构体对应的fd. 570 /// 如果新fd已经打开,则会先关闭新fd. 571 /// 572 /// ## 参数 573 /// 574 /// - `oldfd`:旧文件描述符 575 /// - `newfd`:新文件描述符 576 /// 577 /// ## 返回值 578 /// 579 /// - 成功:新文件描述符 580 /// - 失败:错误码 581 pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> { 582 let binding = ProcessManager::current_pcb().fd_table(); 583 let mut fd_table_guard = binding.write(); 584 return Self::do_dup2(oldfd, newfd, &mut fd_table_guard); 585 } 586 587 fn do_dup2( 588 oldfd: i32, 589 newfd: i32, 590 fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>, 591 ) -> Result<usize, SystemError> { 592 // 确认oldfd, newid是否有效 593 if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) { 594 return Err(SystemError::EBADF); 595 } 596 597 if oldfd == newfd { 598 // 若oldfd与newfd相等 599 return Ok(newfd as usize); 600 } 601 let new_exists = fd_table_guard.get_file_by_fd(newfd).is_some(); 602 if new_exists { 603 // close newfd 604 if let Err(_) = fd_table_guard.drop_fd(newfd) { 605 // An I/O error occurred while attempting to close fildes2. 606 return Err(SystemError::EIO); 607 } 608 } 609 610 let old_file = fd_table_guard 611 .get_file_by_fd(oldfd) 612 .ok_or(SystemError::EBADF)?; 613 let new_file = old_file 614 .lock_no_preempt() 615 .try_clone() 616 .ok_or(SystemError::EBADF)?; 617 // 申请文件描述符,并把文件对象存入其中 618 let res = fd_table_guard 619 .alloc_fd(new_file, Some(newfd)) 620 .map(|x| x as usize); 621 return res; 622 } 623 624 /// # fcntl 625 /// 626 /// ## 参数 627 /// 628 /// - `fd`:文件描述符 629 /// - `cmd`:命令 630 /// - `arg`:参数 631 pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> { 632 match cmd { 633 FcntlCommand::DupFd => { 634 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD { 635 return Err(SystemError::EBADF); 636 } 637 let arg = arg as usize; 638 for i in arg..FileDescriptorVec::PROCESS_MAX_FD { 639 let binding = ProcessManager::current_pcb().fd_table(); 640 let mut fd_table_guard = binding.write(); 641 if fd_table_guard.get_file_by_fd(fd).is_none() { 642 return Self::do_dup2(fd, i as i32, &mut fd_table_guard); 643 } 644 } 645 return Err(SystemError::EMFILE); 646 } 647 FcntlCommand::GetFd => { 648 // Get file descriptor flags. 649 let binding = ProcessManager::current_pcb().fd_table(); 650 let fd_table_guard = binding.read(); 651 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 652 // drop guard 以避免无法调度的问题 653 drop(fd_table_guard); 654 655 if file.lock().close_on_exec() { 656 return Ok(FD_CLOEXEC as usize); 657 } 658 } 659 return Err(SystemError::EBADF); 660 } 661 FcntlCommand::SetFd => { 662 // Set file descriptor flags. 663 let binding = ProcessManager::current_pcb().fd_table(); 664 let fd_table_guard = binding.write(); 665 666 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 667 // drop guard 以避免无法调度的问题 668 drop(fd_table_guard); 669 let arg = arg as u32; 670 if arg & FD_CLOEXEC != 0 { 671 file.lock().set_close_on_exec(true); 672 } else { 673 file.lock().set_close_on_exec(false); 674 } 675 return Ok(0); 676 } 677 return Err(SystemError::EBADF); 678 } 679 680 FcntlCommand::GetFlags => { 681 // Get file status flags. 682 let binding = ProcessManager::current_pcb().fd_table(); 683 let fd_table_guard = binding.read(); 684 685 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 686 // drop guard 以避免无法调度的问题 687 drop(fd_table_guard); 688 return Ok(file.lock_no_preempt().mode().bits() as usize); 689 } 690 691 return Err(SystemError::EBADF); 692 } 693 FcntlCommand::SetFlags => { 694 // Set file status flags. 695 let binding = ProcessManager::current_pcb().fd_table(); 696 let fd_table_guard = binding.write(); 697 698 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 699 let arg = arg as u32; 700 let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?; 701 // drop guard 以避免无法调度的问题 702 drop(fd_table_guard); 703 file.lock_no_preempt().set_mode(mode)?; 704 return Ok(0); 705 } 706 707 return Err(SystemError::EBADF); 708 } 709 _ => { 710 // TODO: unimplemented 711 // 未实现的命令,返回0,不报错。 712 713 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd); 714 return Ok(0); 715 } 716 } 717 } 718 719 /// # ftruncate 720 /// 721 /// ## 描述 722 /// 723 /// 改变文件大小. 724 /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充. 725 /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小. 726 /// 727 /// ## 参数 728 /// 729 /// - `fd`:文件描述符 730 /// - `len`:文件大小 731 /// 732 /// ## 返回值 733 /// 734 /// 如果成功,返回0,否则返回错误码. 735 pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> { 736 let binding = ProcessManager::current_pcb().fd_table(); 737 let fd_table_guard = binding.read(); 738 739 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 740 // drop guard 以避免无法调度的问题 741 drop(fd_table_guard); 742 let r = file.lock_no_preempt().ftruncate(len).map(|_| 0); 743 return r; 744 } 745 746 return Err(SystemError::EBADF); 747 } 748 749 fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> { 750 let binding = ProcessManager::current_pcb().fd_table(); 751 let fd_table_guard = binding.read(); 752 let file = fd_table_guard 753 .get_file_by_fd(fd) 754 .ok_or(SystemError::EBADF)?; 755 // drop guard 以避免无法调度的问题 756 drop(fd_table_guard); 757 758 let mut kstat = PosixKstat::new(); 759 // 获取文件信息 760 let metadata = file.lock().metadata()?; 761 kstat.size = metadata.size as i64; 762 kstat.dev_id = metadata.dev_id as u64; 763 kstat.inode = metadata.inode_id.into() as u64; 764 kstat.blcok_size = metadata.blk_size as i64; 765 kstat.blocks = metadata.blocks as u64; 766 767 kstat.atime.tv_sec = metadata.atime.tv_sec; 768 kstat.atime.tv_nsec = metadata.atime.tv_nsec; 769 kstat.mtime.tv_sec = metadata.mtime.tv_sec; 770 kstat.mtime.tv_nsec = metadata.mtime.tv_nsec; 771 kstat.ctime.tv_sec = metadata.ctime.tv_sec; 772 kstat.ctime.tv_nsec = metadata.ctime.tv_nsec; 773 774 kstat.nlink = metadata.nlinks as u64; 775 kstat.uid = metadata.uid as i32; 776 kstat.gid = metadata.gid as i32; 777 kstat.rdev = metadata.raw_dev as i64; 778 kstat.mode = metadata.mode; 779 match file.lock().file_type() { 780 FileType::File => kstat.mode.insert(ModeType::S_IFREG), 781 FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR), 782 FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK), 783 FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR), 784 FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK), 785 FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK), 786 FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO), 787 FileType::KvmDevice => kstat.mode.insert(ModeType::S_IFCHR), 788 } 789 790 return Ok(kstat); 791 } 792 793 pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 794 let kstat = Self::do_fstat(fd)?; 795 if usr_kstat.is_null() { 796 return Err(SystemError::EFAULT); 797 } 798 unsafe { 799 *usr_kstat = kstat; 800 } 801 return Ok(0); 802 } 803 804 pub fn stat(path: &str, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 805 let fd = Self::open(path, FileMode::O_RDONLY, ModeType::empty(), true)?; 806 let r = Self::fstat(fd as i32, user_kstat); 807 Self::close(fd).ok(); 808 return r; 809 } 810 811 pub fn lstat(path: &str, user_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 812 let fd = Self::open(path, FileMode::O_RDONLY, ModeType::empty(), false)?; 813 let r = Self::fstat(fd as i32, user_kstat); 814 Self::close(fd).ok(); 815 return r; 816 } 817 818 pub fn mknod( 819 path_ptr: *const i8, 820 mode: ModeType, 821 dev_t: DeviceNumber, 822 ) -> Result<usize, SystemError> { 823 // 安全检验 824 let len = unsafe { CStr::from_ptr(path_ptr).to_bytes().len() }; 825 let user_buffer = UserBufferReader::new(path_ptr, len, true)?; 826 let buf = user_buffer.read_from_user::<u8>(0)?; 827 let path = core::str::from_utf8(buf).map_err(|_| SystemError::EINVAL)?; 828 829 // 文件名过长 830 if path.len() > MAX_PATHLEN as usize { 831 return Err(SystemError::ENAMETOOLONG); 832 } 833 834 let inode: Result<Arc<dyn IndexNode>, SystemError> = 835 ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 836 837 if inode.is_ok() { 838 return Err(SystemError::EEXIST); 839 } 840 841 let (filename, parent_path) = rsplit_path(path); 842 843 // 查找父目录 844 let parent_inode: Arc<dyn IndexNode> = ROOT_INODE() 845 .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 846 // 创建nod 847 parent_inode.mknod(filename, mode, dev_t)?; 848 849 return Ok(0); 850 } 851 852 pub fn writev(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> { 853 // IoVecs会进行用户态检验 854 let iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, false) }?; 855 856 let data = iovecs.gather(); 857 858 Self::write(fd, &data) 859 } 860 861 pub fn readv(fd: i32, iov: usize, count: usize) -> Result<usize, SystemError> { 862 // IoVecs会进行用户态检验 863 let mut iovecs = unsafe { IoVecs::from_user(iov as *const IoVec, count, true) }?; 864 865 let mut data = Vec::new(); 866 data.resize(iovecs.0.iter().map(|x| x.len()).sum(), 0); 867 868 let len = Self::read(fd, &mut data)?; 869 870 iovecs.scatter(&data[..len]); 871 872 return Ok(len); 873 } 874 875 pub fn readlink_at( 876 dirfd: i32, 877 path: *const u8, 878 user_buf: *mut u8, 879 buf_size: usize, 880 ) -> Result<usize, SystemError> { 881 let path = check_and_clone_cstr(path, Some(MAX_PATHLEN))?; 882 let mut user_buf = UserBufferWriter::new(user_buf, buf_size, true)?; 883 884 if path.len() == 0 { 885 return Err(SystemError::EINVAL); 886 } 887 888 let (inode, path) = user_path_at(&ProcessManager::current_pcb(), dirfd, &path)?; 889 890 let inode = inode.lookup(path.as_str())?; 891 if inode.metadata()?.file_type != FileType::SymLink { 892 return Err(SystemError::EINVAL); 893 } 894 895 let ubuf = user_buf.buffer::<u8>(0).unwrap(); 896 897 let mut file = File::new(inode, FileMode::O_RDONLY)?; 898 899 let len = file.read(buf_size, ubuf)?; 900 901 return Ok(len); 902 } 903 904 pub fn readlink( 905 path: *const u8, 906 user_buf: *mut u8, 907 buf_size: usize, 908 ) -> Result<usize, SystemError> { 909 return Self::readlink_at(AtFlags::AT_FDCWD.bits(), path, user_buf, buf_size); 910 } 911 912 pub fn access(pathname: *const u8, mode: u32) -> Result<usize, SystemError> { 913 return do_faccessat( 914 AtFlags::AT_FDCWD.bits(), 915 pathname, 916 ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 917 0, 918 ); 919 } 920 921 pub fn faccessat2( 922 dirfd: i32, 923 pathname: *const u8, 924 mode: u32, 925 flags: u32, 926 ) -> Result<usize, SystemError> { 927 return do_faccessat( 928 dirfd, 929 pathname, 930 ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 931 flags, 932 ); 933 } 934 935 pub fn chmod(pathname: *const u8, mode: u32) -> Result<usize, SystemError> { 936 return do_fchmodat( 937 AtFlags::AT_FDCWD.bits(), 938 pathname, 939 ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 940 ); 941 } 942 943 pub fn fchmodat(dirfd: i32, pathname: *const u8, mode: u32) -> Result<usize, SystemError> { 944 return do_fchmodat( 945 dirfd, 946 pathname, 947 ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?, 948 ); 949 } 950 951 pub fn fchmod(fd: i32, mode: u32) -> Result<usize, SystemError> { 952 let _mode = ModeType::from_bits(mode).ok_or(SystemError::EINVAL)?; 953 let binding = ProcessManager::current_pcb().fd_table(); 954 let fd_table_guard = binding.read(); 955 let _file = fd_table_guard 956 .get_file_by_fd(fd) 957 .ok_or(SystemError::EBADF)?; 958 959 // fchmod没完全实现,因此不修改文件的权限 960 // todo: 实现fchmod 961 kwarn!("fchmod not fully implemented"); 962 return Ok(0); 963 } 964 } 965 966 #[repr(C)] 967 #[derive(Debug, Clone, Copy)] 968 pub struct IoVec { 969 /// 缓冲区的起始地址 970 pub iov_base: *mut u8, 971 /// 缓冲区的长度 972 pub iov_len: usize, 973 } 974 975 /// 用于存储多个来自用户空间的IoVec 976 /// 977 /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 978 /// TODO:支持分散读写 979 #[derive(Debug)] 980 pub struct IoVecs(Vec<&'static mut [u8]>); 981 982 impl IoVecs { 983 /// 从用户空间的IoVec中构造IoVecs 984 /// 985 /// @param iov 用户空间的IoVec 986 /// @param iovcnt 用户空间的IoVec的数量 987 /// @param readv 是否为readv系统调用 988 /// 989 /// @return 构造成功返回IoVecs,否则返回错误码 990 pub unsafe fn from_user( 991 iov: *const IoVec, 992 iovcnt: usize, 993 _readv: bool, 994 ) -> Result<Self, SystemError> { 995 // 检查iov指针所在空间是否合法 996 verify_area( 997 VirtAddr::new(iov as usize), 998 iovcnt * core::mem::size_of::<IoVec>(), 999 ) 1000 .map_err(|_| SystemError::EFAULT)?; 1001 1002 // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 1003 let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 1004 1005 let mut slices: Vec<&mut [u8]> = vec![]; 1006 slices.reserve(iovs.len()); 1007 1008 for iov in iovs.iter() { 1009 if iov.iov_len == 0 { 1010 continue; 1011 } 1012 1013 verify_area( 1014 VirtAddr::new(iov.iov_base as usize), 1015 iovcnt * core::mem::size_of::<IoVec>(), 1016 ) 1017 .map_err(|_| SystemError::EFAULT)?; 1018 1019 slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 1020 } 1021 1022 return Ok(Self(slices)); 1023 } 1024 1025 /// @brief 将IoVecs中的数据聚合到一个缓冲区中 1026 /// 1027 /// @return 返回聚合后的缓冲区 1028 pub fn gather(&self) -> Vec<u8> { 1029 let mut buf = Vec::new(); 1030 for slice in self.0.iter() { 1031 buf.extend_from_slice(slice); 1032 } 1033 return buf; 1034 } 1035 1036 /// @brief 将给定的数据分散写入到IoVecs中 1037 pub fn scatter(&mut self, data: &[u8]) { 1038 let mut data: &[u8] = data; 1039 for slice in self.0.iter_mut() { 1040 let len = core::cmp::min(slice.len(), data.len()); 1041 if len == 0 { 1042 continue; 1043 } 1044 1045 slice[..len].copy_from_slice(&data[..len]); 1046 data = &data[len..]; 1047 } 1048 } 1049 1050 /// @brief 创建与IoVecs等长的缓冲区 1051 /// 1052 /// @param set_len 是否设置返回的Vec的len。 1053 /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 1054 /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 1055 /// 1056 /// @return 返回创建的缓冲区 1057 pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 1058 let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 1059 let mut buf: Vec<u8> = Vec::with_capacity(total_len); 1060 1061 if set_len { 1062 buf.resize(total_len, 0); 1063 } 1064 return buf; 1065 } 1066 } 1067