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