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 include::bindings::bindings::{verify_area, AT_REMOVEDIR, PROC_MAX_FD_NUM}, 13 kerror, 14 libs::rwlock::RwLockWriteGuard, 15 mm::VirtAddr, 16 process::ProcessManager, 17 syscall::{user_access::UserBufferReader, Syscall, SystemError}, 18 time::TimeSpec, 19 }; 20 21 use super::{ 22 core::{do_mkdir, do_remove_dir, do_unlink_at}, 23 fcntl::{FcntlCommand, FD_CLOEXEC}, 24 file::{File, FileMode}, 25 utils::rsplit_path, 26 Dirent, FileType, IndexNode, MAX_PATHLEN, ROOT_INODE, VFS_MAX_FOLLOW_SYMLINK_TIMES, 27 }; 28 29 pub const SEEK_SET: u32 = 0; 30 pub const SEEK_CUR: u32 = 1; 31 pub const SEEK_END: u32 = 2; 32 pub const SEEK_MAX: u32 = 3; 33 34 bitflags! { 35 /// 文件类型和权限 36 #[repr(C)] 37 pub struct ModeType: u32 { 38 /// 掩码 39 const S_IFMT = 0o0_170_000; 40 /// 文件类型 41 const S_IFSOCK = 0o140000; 42 const S_IFLNK = 0o120000; 43 const S_IFREG = 0o100000; 44 const S_IFBLK = 0o060000; 45 const S_IFDIR = 0o040000; 46 const S_IFCHR = 0o020000; 47 const S_IFIFO = 0o010000; 48 49 const S_ISUID = 0o004000; 50 const S_ISGID = 0o002000; 51 const S_ISVTX = 0o001000; 52 /// 文件用户权限 53 const S_IRWXU = 0o0700; 54 const S_IRUSR = 0o0400; 55 const S_IWUSR = 0o0200; 56 const S_IXUSR = 0o0100; 57 /// 文件组权限 58 const S_IRWXG = 0o0070; 59 const S_IRGRP = 0o0040; 60 const S_IWGRP = 0o0020; 61 const S_IXGRP = 0o0010; 62 /// 文件其他用户权限 63 const S_IRWXO = 0o0007; 64 const S_IROTH = 0o0004; 65 const S_IWOTH = 0o0002; 66 const S_IXOTH = 0o0001; 67 68 /// 0o777 69 const S_IRWXUGO = Self::S_IRWXU.bits | Self::S_IRWXG.bits | Self::S_IRWXO.bits; 70 /// 0o7777 71 const S_IALLUGO = Self::S_ISUID.bits | Self::S_ISGID.bits | Self::S_ISVTX.bits| Self::S_IRWXUGO.bits; 72 /// 0o444 73 const S_IRUGO = Self::S_IRUSR.bits | Self::S_IRGRP.bits | Self::S_IROTH.bits; 74 /// 0o222 75 const S_IWUGO = Self::S_IWUSR.bits | Self::S_IWGRP.bits | Self::S_IWOTH.bits; 76 /// 0o111 77 const S_IXUGO = Self::S_IXUSR.bits | Self::S_IXGRP.bits | Self::S_IXOTH.bits; 78 79 80 } 81 } 82 83 #[repr(C)] 84 /// # 文件信息结构体 85 pub struct PosixKstat { 86 /// 硬件设备ID 87 dev_id: u64, 88 /// inode号 89 inode: u64, 90 /// 硬链接数 91 nlink: u64, 92 /// 文件权限 93 mode: ModeType, 94 /// 所有者用户ID 95 uid: i32, 96 /// 所有者组ID 97 gid: i32, 98 /// 设备ID 99 rdev: i64, 100 /// 文件大小 101 size: i64, 102 /// 文件系统块大小 103 blcok_size: i64, 104 /// 分配的512B块数 105 blocks: u64, 106 /// 最后访问时间 107 atime: TimeSpec, 108 /// 最后修改时间 109 mtime: TimeSpec, 110 /// 最后状态变化时间 111 ctime: TimeSpec, 112 /// 用于填充结构体大小的空白数据 113 pub _pad: [i8; 24], 114 } 115 impl PosixKstat { 116 fn new() -> Self { 117 Self { 118 inode: 0, 119 dev_id: 0, 120 mode: ModeType { bits: 0 }, 121 nlink: 0, 122 uid: 0, 123 gid: 0, 124 rdev: 0, 125 size: 0, 126 atime: TimeSpec { 127 tv_sec: 0, 128 tv_nsec: 0, 129 }, 130 mtime: TimeSpec { 131 tv_sec: 0, 132 tv_nsec: 0, 133 }, 134 ctime: TimeSpec { 135 tv_sec: 0, 136 tv_nsec: 0, 137 }, 138 blcok_size: 0, 139 blocks: 0, 140 _pad: Default::default(), 141 } 142 } 143 } 144 impl Syscall { 145 /// @brief 为当前进程打开一个文件 146 /// 147 /// @param path 文件路径 148 /// @param o_flags 打开文件的标志位 149 /// 150 /// @return 文件描述符编号,或者是错误码 151 pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> { 152 // kdebug!("open: path: {}, mode: {:?}", path, mode); 153 154 // 文件名过长 155 if path.len() > MAX_PATHLEN as usize { 156 return Err(SystemError::ENAMETOOLONG); 157 } 158 159 let inode: Result<Arc<dyn IndexNode>, SystemError> = 160 ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 161 162 let inode: Arc<dyn IndexNode> = if inode.is_err() { 163 let errno = inode.unwrap_err(); 164 // 文件不存在,且需要创建 165 if mode.contains(FileMode::O_CREAT) 166 && !mode.contains(FileMode::O_DIRECTORY) 167 && errno == SystemError::ENOENT 168 { 169 let (filename, parent_path) = rsplit_path(path); 170 // 查找父目录 171 let parent_inode: Arc<dyn IndexNode> = 172 ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; 173 // 创建文件 174 let inode: Arc<dyn IndexNode> = parent_inode.create( 175 filename, 176 FileType::File, 177 ModeType::from_bits_truncate(0o755), 178 )?; 179 inode 180 } else { 181 // 不需要创建文件,因此返回错误码 182 return Err(errno); 183 } 184 } else { 185 inode.unwrap() 186 }; 187 188 let file_type: FileType = inode.metadata()?.file_type; 189 // 如果要打开的是文件夹,而目标不是文件夹 190 if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir { 191 return Err(SystemError::ENOTDIR); 192 } 193 194 // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件 195 if mode.contains(FileMode::O_TRUNC) 196 && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY)) 197 && file_type == FileType::File 198 { 199 inode.truncate(0)?; 200 } 201 202 // 创建文件对象 203 204 let mut file: File = File::new(inode, mode)?; 205 206 // 打开模式为“追加” 207 if mode.contains(FileMode::O_APPEND) { 208 file.lseek(SeekFrom::SeekEnd(0))?; 209 } 210 211 // 把文件对象存入pcb 212 let r = ProcessManager::current_pcb() 213 .fd_table() 214 .write() 215 .alloc_fd(file, None) 216 .map(|fd| fd as usize); 217 218 return r; 219 } 220 221 /// @brief 关闭文件 222 /// 223 /// @param fd 文件描述符编号 224 /// 225 /// @return 成功返回0,失败返回错误码 226 pub fn close(fd: usize) -> Result<usize, SystemError> { 227 let binding = ProcessManager::current_pcb().fd_table(); 228 let mut fd_table_guard = binding.write(); 229 230 let res = fd_table_guard.drop_fd(fd as i32).map(|_| 0); 231 232 return res; 233 } 234 235 /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 236 /// 237 /// @param fd 文件描述符编号 238 /// @param buf 输出缓冲区。 239 /// 240 /// @return Ok(usize) 成功读取的数据的字节数 241 /// @return Err(SystemError) 读取失败,返回posix错误码 242 pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 243 let binding = ProcessManager::current_pcb().fd_table(); 244 let fd_table_guard = binding.read(); 245 246 let file = fd_table_guard.get_file_by_fd(fd); 247 if file.is_none() { 248 return Err(SystemError::EBADF); 249 } 250 // drop guard 以避免无法调度的问题 251 drop(fd_table_guard); 252 let file = file.unwrap(); 253 254 return file.lock_no_preempt().read(buf.len(), buf); 255 } 256 257 /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 258 /// 259 /// @param fd 文件描述符编号 260 /// @param buf 输入缓冲区。 261 /// 262 /// @return Ok(usize) 成功写入的数据的字节数 263 /// @return Err(SystemError) 写入失败,返回posix错误码 264 pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> { 265 let binding = ProcessManager::current_pcb().fd_table(); 266 let fd_table_guard = binding.read(); 267 268 let file = fd_table_guard 269 .get_file_by_fd(fd) 270 .ok_or(SystemError::EBADF)?; 271 272 // drop guard 以避免无法调度的问题 273 drop(fd_table_guard); 274 return file.lock_no_preempt().write(buf.len(), buf); 275 } 276 277 /// @brief 调整文件操作指针的位置 278 /// 279 /// @param fd 文件描述符编号 280 /// @param seek 调整的方式 281 /// 282 /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量 283 /// @return Err(SystemError) 调整失败,返回posix错误码 284 pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> { 285 let binding = ProcessManager::current_pcb().fd_table(); 286 let fd_table_guard = binding.read(); 287 let file = fd_table_guard 288 .get_file_by_fd(fd) 289 .ok_or(SystemError::EBADF)?; 290 291 // drop guard 以避免无法调度的问题 292 drop(fd_table_guard); 293 return file.lock_no_preempt().lseek(seek); 294 } 295 296 /// @brief 切换工作目录 297 /// 298 /// @param dest_path 目标路径 299 /// 300 /// @return 返回码 描述 301 /// 0 | 成功 302 /// 303 /// EACCESS | 权限不足 304 /// 305 /// ELOOP | 解析path时遇到路径循环 306 /// 307 /// ENAMETOOLONG | 路径名过长 308 /// 309 /// ENOENT | 目标文件或目录不存在 310 /// 311 /// ENODIR | 检索期间发现非目录项 312 /// 313 /// ENOMEM | 系统内存不足 314 /// 315 /// EFAULT | 错误的地址 316 /// 317 /// ENAMETOOLONG | 路径过长 318 pub fn chdir(dest_path: &str) -> Result<usize, SystemError> { 319 let proc = ProcessManager::current_pcb(); 320 // Copy path to kernel space to avoid some security issues 321 let path = dest_path.to_string(); 322 let mut new_path = String::from(""); 323 if path.len() > 0 { 324 let cwd = match path.as_bytes()[0] { 325 b'/' => String::from("/"), 326 _ => proc.basic().cwd(), 327 }; 328 let mut cwd_vec: Vec<_> = cwd.split("/").filter(|&x| x != "").collect(); 329 let path_split = path.split("/").filter(|&x| x != ""); 330 for seg in path_split { 331 if seg == ".." { 332 cwd_vec.pop(); 333 } else if seg == "." { 334 // 当前目录 335 } else { 336 cwd_vec.push(seg); 337 } 338 } 339 //proc.basic().set_path(String::from("")); 340 for seg in cwd_vec { 341 new_path.push_str("/"); 342 new_path.push_str(seg); 343 } 344 if new_path == "" { 345 new_path = String::from("/"); 346 } 347 } 348 let inode = 349 match ROOT_INODE().lookup_follow_symlink(&new_path, VFS_MAX_FOLLOW_SYMLINK_TIMES) { 350 Err(e) => { 351 kerror!("Change Directory Failed, Error = {:?}", e); 352 return Err(SystemError::ENOENT); 353 } 354 Ok(i) => i, 355 }; 356 let metadata = inode.metadata()?; 357 if metadata.file_type == FileType::Dir { 358 proc.basic_mut().set_cwd(String::from(new_path)); 359 return Ok(0); 360 } else { 361 return Err(SystemError::ENOTDIR); 362 } 363 } 364 365 /// @brief 获取当前进程的工作目录路径 366 /// 367 /// @param buf 指向缓冲区的指针 368 /// @param size 缓冲区的大小 369 /// 370 /// @return 成功,返回的指针指向包含工作目录路径的字符串 371 /// @return 错误,没有足够的空间 372 pub fn getcwd(buf: &mut [u8]) -> Result<VirtAddr, SystemError> { 373 let proc = ProcessManager::current_pcb(); 374 let cwd = proc.basic().cwd(); 375 376 let cwd_bytes = cwd.as_bytes(); 377 let cwd_len = cwd_bytes.len(); 378 if cwd_len + 1 > buf.len() { 379 return Err(SystemError::ENOMEM); 380 } 381 buf[..cwd_len].copy_from_slice(cwd_bytes); 382 buf[cwd_len] = 0; 383 384 return Ok(VirtAddr::new(buf.as_ptr() as usize)); 385 } 386 387 /// @brief 获取目录中的数据 388 /// 389 /// TODO: 这个函数的语义与Linux不一致,需要修改!!! 390 /// 391 /// @param fd 文件描述符号 392 /// @param buf 输出缓冲区 393 /// 394 /// @return 成功返回读取的字节数,失败返回错误码 395 pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 396 let dirent = 397 unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?; 398 399 if fd < 0 || fd as u32 > PROC_MAX_FD_NUM { 400 return Err(SystemError::EBADF); 401 } 402 403 // 获取fd 404 let binding = ProcessManager::current_pcb().fd_table(); 405 let fd_table_guard = binding.read(); 406 let file = fd_table_guard 407 .get_file_by_fd(fd) 408 .ok_or(SystemError::EBADF)?; 409 410 // drop guard 以避免无法调度的问题 411 drop(fd_table_guard); 412 413 let res = file.lock_no_preempt().readdir(dirent).map(|x| x as usize); 414 415 return res; 416 } 417 418 /// @brief 创建文件夹 419 /// 420 /// @param path(r8) 路径 / mode(r9) 模式 421 /// 422 /// @return uint64_t 负数错误码 / 0表示成功 423 pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> { 424 return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); 425 } 426 427 /// **删除文件夹、取消文件的链接、删除文件的系统调用** 428 /// 429 /// ## 参数 430 /// 431 /// - `dirfd`:文件夹的文件描述符.目前暂未实现 432 /// - `pathname`:文件夹的路径 433 /// - `flags`:标志位 434 /// 435 /// 436 pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> { 437 // kdebug!("sys_unlink_at={path:?}"); 438 if (flags & (!AT_REMOVEDIR)) != 0 { 439 return Err(SystemError::EINVAL); 440 } 441 442 if (flags & AT_REMOVEDIR) > 0 { 443 // kdebug!("rmdir"); 444 match do_remove_dir(&pathname) { 445 Err(err) => { 446 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 447 return Err(err); 448 } 449 Ok(_) => { 450 return Ok(0); 451 } 452 } 453 } 454 455 match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) { 456 Err(err) => { 457 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 458 return Err(err); 459 } 460 Ok(_) => { 461 return Ok(0); 462 } 463 } 464 } 465 466 /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 467 pub fn dup(oldfd: i32) -> Result<usize, SystemError> { 468 let binding = ProcessManager::current_pcb().fd_table(); 469 let mut fd_table_guard = binding.write(); 470 471 let old_file = fd_table_guard 472 .get_file_by_fd(oldfd) 473 .ok_or(SystemError::EBADF)?; 474 475 let new_file = old_file 476 .lock_no_preempt() 477 .try_clone() 478 .ok_or(SystemError::EBADF)?; 479 // 申请文件描述符,并把文件对象存入其中 480 let res = fd_table_guard.alloc_fd(new_file, None).map(|x| x as usize); 481 return res; 482 } 483 484 /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 485 /// 并返回新复制的文件结构体对应的fd. 486 /// 如果新fd已经打开,则会先关闭新fd. 487 /// 488 /// ## 参数 489 /// 490 /// - `oldfd`:旧文件描述符 491 /// - `newfd`:新文件描述符 492 /// 493 /// ## 返回值 494 /// 495 /// - 成功:新文件描述符 496 /// - 失败:错误码 497 pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> { 498 let binding = ProcessManager::current_pcb().fd_table(); 499 let mut fd_table_guard = binding.write(); 500 return Self::do_dup2(oldfd, newfd, &mut fd_table_guard); 501 } 502 503 fn do_dup2( 504 oldfd: i32, 505 newfd: i32, 506 fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>, 507 ) -> Result<usize, SystemError> { 508 // 确认oldfd, newid是否有效 509 if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) { 510 return Err(SystemError::EBADF); 511 } 512 513 if oldfd == newfd { 514 // 若oldfd与newfd相等 515 return Ok(newfd as usize); 516 } 517 let new_exists = fd_table_guard.get_file_by_fd(newfd).is_some(); 518 if new_exists { 519 // close newfd 520 if let Err(_) = fd_table_guard.drop_fd(newfd) { 521 // An I/O error occurred while attempting to close fildes2. 522 return Err(SystemError::EIO); 523 } 524 } 525 526 let old_file = fd_table_guard 527 .get_file_by_fd(oldfd) 528 .ok_or(SystemError::EBADF)?; 529 let new_file = old_file 530 .lock_no_preempt() 531 .try_clone() 532 .ok_or(SystemError::EBADF)?; 533 // 申请文件描述符,并把文件对象存入其中 534 let res = fd_table_guard 535 .alloc_fd(new_file, Some(newfd)) 536 .map(|x| x as usize); 537 return res; 538 } 539 540 /// # fcntl 541 /// 542 /// ## 参数 543 /// 544 /// - `fd`:文件描述符 545 /// - `cmd`:命令 546 /// - `arg`:参数 547 pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> { 548 match cmd { 549 FcntlCommand::DupFd => { 550 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD { 551 return Err(SystemError::EBADF); 552 } 553 let arg = arg as usize; 554 for i in arg..FileDescriptorVec::PROCESS_MAX_FD { 555 let binding = ProcessManager::current_pcb().fd_table(); 556 let mut fd_table_guard = binding.write(); 557 if fd_table_guard.get_file_by_fd(fd).is_none() { 558 return Self::do_dup2(fd, i as i32, &mut fd_table_guard); 559 } 560 } 561 return Err(SystemError::EMFILE); 562 } 563 FcntlCommand::GetFd => { 564 // Get file descriptor flags. 565 let binding = ProcessManager::current_pcb().fd_table(); 566 let fd_table_guard = binding.read(); 567 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 568 // drop guard 以避免无法调度的问题 569 drop(fd_table_guard); 570 571 if file.lock().close_on_exec() { 572 return Ok(FD_CLOEXEC as usize); 573 } 574 } 575 return Err(SystemError::EBADF); 576 } 577 FcntlCommand::SetFd => { 578 // Set file descriptor flags. 579 let binding = ProcessManager::current_pcb().fd_table(); 580 let fd_table_guard = binding.write(); 581 582 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 583 // drop guard 以避免无法调度的问题 584 drop(fd_table_guard); 585 let arg = arg as u32; 586 if arg & FD_CLOEXEC != 0 { 587 file.lock().set_close_on_exec(true); 588 } else { 589 file.lock().set_close_on_exec(false); 590 } 591 return Ok(0); 592 } 593 return Err(SystemError::EBADF); 594 } 595 596 FcntlCommand::GetFlags => { 597 // Get file status flags. 598 let binding = ProcessManager::current_pcb().fd_table(); 599 let fd_table_guard = binding.read(); 600 601 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 602 // drop guard 以避免无法调度的问题 603 drop(fd_table_guard); 604 return Ok(file.lock_no_preempt().mode().bits() as usize); 605 } 606 607 return Err(SystemError::EBADF); 608 } 609 FcntlCommand::SetFlags => { 610 // Set file status flags. 611 let binding = ProcessManager::current_pcb().fd_table(); 612 let fd_table_guard = binding.write(); 613 614 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 615 let arg = arg as u32; 616 let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?; 617 // drop guard 以避免无法调度的问题 618 drop(fd_table_guard); 619 file.lock_no_preempt().set_mode(mode)?; 620 return Ok(0); 621 } 622 623 return Err(SystemError::EBADF); 624 } 625 _ => { 626 // TODO: unimplemented 627 // 未实现的命令,返回0,不报错。 628 629 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd); 630 return Ok(0); 631 } 632 } 633 } 634 635 /// # ftruncate 636 /// 637 /// ## 描述 638 /// 639 /// 改变文件大小. 640 /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充. 641 /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小. 642 /// 643 /// ## 参数 644 /// 645 /// - `fd`:文件描述符 646 /// - `len`:文件大小 647 /// 648 /// ## 返回值 649 /// 650 /// 如果成功,返回0,否则返回错误码. 651 pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> { 652 let binding = ProcessManager::current_pcb().fd_table(); 653 let fd_table_guard = binding.read(); 654 655 if let Some(file) = fd_table_guard.get_file_by_fd(fd) { 656 // drop guard 以避免无法调度的问题 657 drop(fd_table_guard); 658 let r = file.lock_no_preempt().ftruncate(len).map(|_| 0); 659 return r; 660 } 661 662 return Err(SystemError::EBADF); 663 } 664 665 fn do_fstat(fd: i32) -> Result<PosixKstat, SystemError> { 666 let binding = ProcessManager::current_pcb().fd_table(); 667 let fd_table_guard = binding.read(); 668 let file = fd_table_guard 669 .get_file_by_fd(fd) 670 .ok_or(SystemError::EBADF)?; 671 // drop guard 以避免无法调度的问题 672 drop(fd_table_guard); 673 674 let mut kstat = PosixKstat::new(); 675 // 获取文件信息 676 let metadata = file.lock().metadata()?; 677 kstat.size = metadata.size as i64; 678 kstat.dev_id = metadata.dev_id as u64; 679 kstat.inode = metadata.inode_id.into() as u64; 680 kstat.blcok_size = metadata.blk_size as i64; 681 kstat.blocks = metadata.blocks as u64; 682 683 kstat.atime.tv_sec = metadata.atime.tv_sec; 684 kstat.atime.tv_nsec = metadata.atime.tv_nsec; 685 kstat.mtime.tv_sec = metadata.mtime.tv_sec; 686 kstat.mtime.tv_nsec = metadata.mtime.tv_nsec; 687 kstat.ctime.tv_sec = metadata.ctime.tv_sec; 688 kstat.ctime.tv_nsec = metadata.ctime.tv_nsec; 689 690 kstat.nlink = metadata.nlinks as u64; 691 kstat.uid = metadata.uid as i32; 692 kstat.gid = metadata.gid as i32; 693 kstat.rdev = metadata.raw_dev as i64; 694 kstat.mode = metadata.mode; 695 match file.lock().file_type() { 696 FileType::File => kstat.mode.insert(ModeType::S_IFMT), 697 FileType::Dir => kstat.mode.insert(ModeType::S_IFDIR), 698 FileType::BlockDevice => kstat.mode.insert(ModeType::S_IFBLK), 699 FileType::CharDevice => kstat.mode.insert(ModeType::S_IFCHR), 700 FileType::SymLink => kstat.mode.insert(ModeType::S_IFLNK), 701 FileType::Socket => kstat.mode.insert(ModeType::S_IFSOCK), 702 FileType::Pipe => kstat.mode.insert(ModeType::S_IFIFO), 703 } 704 705 return Ok(kstat); 706 } 707 708 pub fn fstat(fd: i32, usr_kstat: *mut PosixKstat) -> Result<usize, SystemError> { 709 let kstat = Self::do_fstat(fd)?; 710 if usr_kstat.is_null() { 711 return Err(SystemError::EFAULT); 712 } 713 unsafe { 714 *usr_kstat = kstat; 715 } 716 return Ok(0); 717 } 718 719 pub fn mknod( 720 path_ptr: *const i8, 721 mode: ModeType, 722 dev_t: DeviceNumber, 723 ) -> Result<usize, SystemError> { 724 // 安全检验 725 let len = unsafe { CStr::from_ptr(path_ptr).to_bytes().len() }; 726 let user_buffer = UserBufferReader::new(path_ptr, len, true)?; 727 let buf = user_buffer.read_from_user::<u8>(0)?; 728 let path = core::str::from_utf8(buf).map_err(|_| SystemError::EINVAL)?; 729 730 // 文件名过长 731 if path.len() > MAX_PATHLEN as usize { 732 return Err(SystemError::ENAMETOOLONG); 733 } 734 735 let inode: Result<Arc<dyn IndexNode>, SystemError> = 736 ROOT_INODE().lookup_follow_symlink(path, VFS_MAX_FOLLOW_SYMLINK_TIMES); 737 738 if inode.is_ok() { 739 return Err(SystemError::EEXIST); 740 } 741 742 let (filename, parent_path) = rsplit_path(path); 743 744 // 查找父目录 745 let parent_inode: Arc<dyn IndexNode> = ROOT_INODE() 746 .lookup_follow_symlink(parent_path.unwrap_or("/"), VFS_MAX_FOLLOW_SYMLINK_TIMES)?; 747 // 创建nod 748 parent_inode.mknod(filename, mode, dev_t)?; 749 750 return Ok(0); 751 } 752 } 753 #[repr(C)] 754 #[derive(Debug, Clone, Copy)] 755 pub struct IoVec { 756 /// 缓冲区的起始地址 757 pub iov_base: *mut u8, 758 /// 缓冲区的长度 759 pub iov_len: usize, 760 } 761 762 /// 用于存储多个来自用户空间的IoVec 763 /// 764 /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 765 /// TODO:支持分散读写 766 #[derive(Debug)] 767 pub struct IoVecs(Vec<&'static mut [u8]>); 768 769 impl IoVecs { 770 /// 从用户空间的IoVec中构造IoVecs 771 /// 772 /// @param iov 用户空间的IoVec 773 /// @param iovcnt 用户空间的IoVec的数量 774 /// @param readv 是否为readv系统调用 775 /// 776 /// @return 构造成功返回IoVecs,否则返回错误码 777 pub unsafe fn from_user( 778 iov: *const IoVec, 779 iovcnt: usize, 780 _readv: bool, 781 ) -> Result<Self, SystemError> { 782 // 检查iov指针所在空间是否合法 783 if !verify_area( 784 iov as usize as u64, 785 (iovcnt * core::mem::size_of::<IoVec>()) as u64, 786 ) { 787 return Err(SystemError::EFAULT); 788 } 789 790 // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 791 let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 792 793 let mut slices: Vec<&mut [u8]> = vec![]; 794 slices.reserve(iovs.len()); 795 796 for iov in iovs.iter() { 797 if iov.iov_len == 0 { 798 continue; 799 } 800 801 if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) { 802 return Err(SystemError::EFAULT); 803 } 804 805 slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 806 } 807 808 return Ok(Self(slices)); 809 } 810 811 /// @brief 将IoVecs中的数据聚合到一个缓冲区中 812 /// 813 /// @return 返回聚合后的缓冲区 814 pub fn gather(&self) -> Vec<u8> { 815 let mut buf = Vec::new(); 816 for slice in self.0.iter() { 817 buf.extend_from_slice(slice); 818 } 819 return buf; 820 } 821 822 /// @brief 将给定的数据分散写入到IoVecs中 823 pub fn scatter(&mut self, data: &[u8]) { 824 let mut data: &[u8] = data; 825 for slice in self.0.iter_mut() { 826 let len = core::cmp::min(slice.len(), data.len()); 827 if len == 0 { 828 continue; 829 } 830 831 slice[..len].copy_from_slice(&data[..len]); 832 data = &data[len..]; 833 } 834 } 835 836 /// @brief 创建与IoVecs等长的缓冲区 837 /// 838 /// @param set_len 是否设置返回的Vec的len。 839 /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 840 /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 841 /// 842 /// @return 返回创建的缓冲区 843 pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 844 let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 845 let mut buf: Vec<u8> = Vec::with_capacity(total_len); 846 847 if set_len { 848 buf.resize(total_len, 0); 849 } 850 return buf; 851 } 852 } 853