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