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