1 use alloc::{boxed::Box, sync::Arc, vec::Vec}; 2 3 use crate::{ 4 arch::asm::current::current_pcb, 5 filesystem::vfs::file::FileDescriptorVec, 6 include::bindings::bindings::{verify_area, AT_REMOVEDIR, PAGE_4K_SIZE, PROC_MAX_FD_NUM}, 7 io::SeekFrom, 8 kerror, 9 syscall::{Syscall, SystemError}, 10 }; 11 12 use super::{ 13 core::{do_mkdir, do_remove_dir, do_unlink_at}, 14 fcntl::{FcntlCommand, FD_CLOEXEC}, 15 file::{File, FileMode}, 16 utils::rsplit_path, 17 Dirent, FileType, IndexNode, ROOT_INODE, 18 }; 19 20 pub const SEEK_SET: u32 = 0; 21 pub const SEEK_CUR: u32 = 1; 22 pub const SEEK_END: u32 = 2; 23 pub const SEEK_MAX: u32 = 3; 24 25 impl Syscall { 26 /// @brief 为当前进程打开一个文件 27 /// 28 /// @param path 文件路径 29 /// @param o_flags 打开文件的标志位 30 /// 31 /// @return 文件描述符编号,或者是错误码 32 pub fn open(path: &str, mode: FileMode) -> Result<usize, SystemError> { 33 // kdebug!("open: path: {}, mode: {:?}", path, mode); 34 // 文件名过长 35 if path.len() > PAGE_4K_SIZE as usize { 36 return Err(SystemError::ENAMETOOLONG); 37 } 38 39 let inode: Result<Arc<dyn IndexNode>, SystemError> = ROOT_INODE().lookup(path); 40 41 let inode: Arc<dyn IndexNode> = if inode.is_err() { 42 let errno = inode.unwrap_err(); 43 // 文件不存在,且需要创建 44 if mode.contains(FileMode::O_CREAT) 45 && !mode.contains(FileMode::O_DIRECTORY) 46 && errno == SystemError::ENOENT 47 { 48 let (filename, parent_path) = rsplit_path(path); 49 // 查找父目录 50 let parent_inode: Arc<dyn IndexNode> = 51 ROOT_INODE().lookup(parent_path.unwrap_or("/"))?; 52 // 创建文件 53 let inode: Arc<dyn IndexNode> = 54 parent_inode.create(filename, FileType::File, 0o777)?; 55 inode 56 } else { 57 // 不需要创建文件,因此返回错误码 58 return Err(errno); 59 } 60 } else { 61 inode.unwrap() 62 }; 63 64 let file_type: FileType = inode.metadata()?.file_type; 65 // 如果要打开的是文件夹,而目标不是文件夹 66 if mode.contains(FileMode::O_DIRECTORY) && file_type != FileType::Dir { 67 return Err(SystemError::ENOTDIR); 68 } 69 70 // 如果O_TRUNC,并且,打开模式包含O_RDWR或O_WRONLY,清空文件 71 if mode.contains(FileMode::O_TRUNC) 72 && (mode.contains(FileMode::O_RDWR) || mode.contains(FileMode::O_WRONLY)) 73 && file_type == FileType::File 74 { 75 inode.truncate(0)?; 76 } 77 78 // 创建文件对象 79 let mut file: File = File::new(inode, mode)?; 80 81 // 打开模式为“追加” 82 if mode.contains(FileMode::O_APPEND) { 83 file.lseek(SeekFrom::SeekEnd(0))?; 84 } 85 86 // 把文件对象存入pcb 87 let r = current_pcb().alloc_fd(file, None).map(|fd| fd as usize); 88 // kdebug!("open: fd: {:?}", r); 89 return r; 90 } 91 92 /// @brief 关闭文件 93 /// 94 /// @param fd 文件描述符编号 95 /// 96 /// @return 成功返回0,失败返回错误码 97 pub fn close(fd: usize) -> Result<usize, SystemError> { 98 // kdebug!("syscall::close: fd: {}", fd); 99 return current_pcb().drop_fd(fd as i32).map(|_| 0); 100 } 101 102 /// @brief 根据文件描述符,读取文件数据。尝试读取的数据长度与buf的长度相同。 103 /// 104 /// @param fd 文件描述符编号 105 /// @param buf 输出缓冲区。 106 /// 107 /// @return Ok(usize) 成功读取的数据的字节数 108 /// @return Err(SystemError) 读取失败,返回posix错误码 109 pub fn read(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 110 // kdebug!("syscall::read: fd: {}, len={}", fd, buf.len()); 111 let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 112 if file.is_none() { 113 return Err(SystemError::EBADF); 114 } 115 let file: &mut File = file.unwrap(); 116 117 return file.read(buf.len(), buf); 118 } 119 120 /// @brief 根据文件描述符,向文件写入数据。尝试写入的数据长度与buf的长度相同。 121 /// 122 /// @param fd 文件描述符编号 123 /// @param buf 输入缓冲区。 124 /// 125 /// @return Ok(usize) 成功写入的数据的字节数 126 /// @return Err(SystemError) 写入失败,返回posix错误码 127 pub fn write(fd: i32, buf: &[u8]) -> Result<usize, SystemError> { 128 // kdebug!("syscall::write: fd: {}, len={}", fd, buf.len()); 129 let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 130 if file.is_none() { 131 return Err(SystemError::EBADF); 132 } 133 let file: &mut File = file.unwrap(); 134 135 return file.write(buf.len(), buf); 136 } 137 138 /// @brief 调整文件操作指针的位置 139 /// 140 /// @param fd 文件描述符编号 141 /// @param seek 调整的方式 142 /// 143 /// @return Ok(usize) 调整后,文件访问指针相对于文件头部的偏移量 144 /// @return Err(SystemError) 调整失败,返回posix错误码 145 pub fn lseek(fd: i32, seek: SeekFrom) -> Result<usize, SystemError> { 146 // kdebug!("syscall::lseek: fd: {}, seek={:?}", fd, seek); 147 let file: Option<&mut File> = current_pcb().get_file_mut_by_fd(fd); 148 if file.is_none() { 149 return Err(SystemError::EBADF); 150 } 151 let file: &mut File = file.unwrap(); 152 return file.lseek(seek); 153 } 154 155 /// @brief 切换工作目录 156 /// 157 /// @param dest_path 目标路径 158 /// 159 /// @return 返回码 描述 160 /// 0 | 成功 161 /// 162 /// EACCESS | 权限不足 163 /// 164 /// ELOOP | 解析path时遇到路径循环 165 /// 166 /// ENAMETOOLONG | 路径名过长 167 /// 168 /// ENOENT | 目标文件或目录不存在 169 /// 170 /// ENODIR | 检索期间发现非目录项 171 /// 172 /// ENOMEM | 系统内存不足 173 /// 174 /// EFAULT | 错误的地址 175 /// 176 /// ENAMETOOLONG | 路径过长 177 pub fn chdir(dest_path: &str) -> Result<usize, SystemError> { 178 // Copy path to kernel space to avoid some security issues 179 let path: Box<&str> = Box::new(dest_path); 180 let inode = match ROOT_INODE().lookup(&path) { 181 Err(e) => { 182 kerror!("Change Directory Failed, Error = {:?}", e); 183 return Err(SystemError::ENOENT); 184 } 185 Ok(i) => i, 186 }; 187 188 match inode.metadata() { 189 Err(e) => { 190 kerror!("INode Get MetaData Failed, Error = {:?}", e); 191 return Err(SystemError::ENOENT); 192 } 193 Ok(i) => { 194 if let FileType::Dir = i.file_type { 195 return Ok(0); 196 } else { 197 return Err(SystemError::ENOTDIR); 198 } 199 } 200 } 201 } 202 203 /// @brief 获取目录中的数据 204 /// 205 /// TODO: 这个函数的语义与Linux不一致,需要修改!!! 206 /// 207 /// @param fd 文件描述符号 208 /// @param buf 输出缓冲区 209 /// 210 /// @return 成功返回读取的字节数,失败返回错误码 211 pub fn getdents(fd: i32, buf: &mut [u8]) -> Result<usize, SystemError> { 212 let dirent = 213 unsafe { (buf.as_mut_ptr() as *mut Dirent).as_mut() }.ok_or(SystemError::EFAULT)?; 214 215 if fd < 0 || fd as u32 > PROC_MAX_FD_NUM { 216 return Err(SystemError::EBADF); 217 } 218 219 // 获取fd 220 let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) { 221 None => { 222 return Err(SystemError::EBADF); 223 } 224 Some(file) => file, 225 }; 226 // kdebug!("file={file:?}"); 227 228 return file.readdir(dirent).map(|x| x as usize); 229 } 230 231 /// @brief 创建文件夹 232 /// 233 /// @param path(r8) 路径 / mode(r9) 模式 234 /// 235 /// @return uint64_t 负数错误码 / 0表示成功 236 pub fn mkdir(path: &str, mode: usize) -> Result<usize, SystemError> { 237 return do_mkdir(path, FileMode::from_bits_truncate(mode as u32)).map(|x| x as usize); 238 } 239 240 /// **删除文件夹、取消文件的链接、删除文件的系统调用** 241 /// 242 /// ## 参数 243 /// 244 /// - `dirfd`:文件夹的文件描述符.目前暂未实现 245 /// - `pathname`:文件夹的路径 246 /// - `flags`:标志位 247 /// 248 /// 249 pub fn unlinkat(_dirfd: i32, pathname: &str, flags: u32) -> Result<usize, SystemError> { 250 // kdebug!("sys_unlink_at={path:?}"); 251 if (flags & (!AT_REMOVEDIR)) != 0 { 252 return Err(SystemError::EINVAL); 253 } 254 255 if (flags & AT_REMOVEDIR) > 0 { 256 // kdebug!("rmdir"); 257 match do_remove_dir(&pathname) { 258 Err(err) => { 259 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 260 return Err(err); 261 } 262 Ok(_) => { 263 return Ok(0); 264 } 265 } 266 } 267 268 match do_unlink_at(&pathname, FileMode::from_bits_truncate(flags as u32)) { 269 Err(err) => { 270 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 271 return Err(err); 272 } 273 Ok(_) => { 274 return Ok(0); 275 } 276 } 277 } 278 279 /// @brief 根据提供的文件描述符的fd,复制对应的文件结构体,并返回新复制的文件结构体对应的fd 280 pub fn dup(oldfd: i32) -> Result<usize, SystemError> { 281 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 282 // 获得当前文件描述符数组 283 // 确认oldfd是否有效 284 if FileDescriptorVec::validate_fd(oldfd) { 285 if let Some(file) = &fds.fds[oldfd as usize] { 286 // 尝试获取对应的文件结构体 287 let file_cp: Box<File> = file.try_clone().ok_or(SystemError::EBADF)?; 288 289 // 申请文件描述符,并把文件对象存入其中 290 let res = current_pcb().alloc_fd(*file_cp, None).map(|x| x as usize); 291 return res; 292 } 293 // oldfd对应的文件不存在 294 return Err(SystemError::EBADF); 295 } 296 return Err(SystemError::EBADF); 297 } else { 298 return Err(SystemError::EMFILE); 299 } 300 } 301 302 /// 根据提供的文件描述符的fd,和指定新fd,复制对应的文件结构体, 303 /// 并返回新复制的文件结构体对应的fd. 304 /// 如果新fd已经打开,则会先关闭新fd. 305 /// 306 /// ## 参数 307 /// 308 /// - `oldfd`:旧文件描述符 309 /// - `newfd`:新文件描述符 310 /// 311 /// ## 返回值 312 /// 313 /// - 成功:新文件描述符 314 /// - 失败:错误码 315 pub fn dup2(oldfd: i32, newfd: i32) -> Result<usize, SystemError> { 316 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 317 // 获得当前文件描述符数组 318 if FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd) { 319 //确认oldfd, newid是否有效 320 if oldfd == newfd { 321 // 若oldfd与newfd相等 322 return Ok(newfd as usize); 323 } 324 325 if let Some(file) = &fds.fds[oldfd as usize] { 326 if fds.fds[newfd as usize].is_some() { 327 // close newfd 328 if let Err(_) = current_pcb().drop_fd(newfd) { 329 // An I/O error occurred while attempting to close fildes2. 330 return Err(SystemError::EIO); 331 } 332 } 333 334 // 尝试获取对应的文件结构体 335 let file_cp = file.try_clone(); 336 if file_cp.is_none() { 337 return Err(SystemError::EBADF); 338 } 339 // 申请文件描述符,并把文件对象存入其中 340 let res = current_pcb() 341 .alloc_fd(*file_cp.unwrap(), Some(newfd)) 342 .map(|x| x as usize); 343 344 return res; 345 } 346 return Err(SystemError::EBADF); 347 } else { 348 return Err(SystemError::EBADF); 349 } 350 } 351 // 从pcb获取文件描述符数组失败 352 return Err(SystemError::EMFILE); 353 } 354 355 /// # fcntl 356 /// 357 /// ## 参数 358 /// 359 /// - `fd`:文件描述符 360 /// - `cmd`:命令 361 /// - `arg`:参数 362 pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> { 363 match cmd { 364 FcntlCommand::DupFd => { 365 if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD { 366 return Err(SystemError::EBADF); 367 } 368 let arg = arg as usize; 369 for i in arg..FileDescriptorVec::PROCESS_MAX_FD { 370 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 371 if fds.fds[i as usize].is_none() { 372 return Self::dup2(fd, i as i32); 373 } 374 } 375 } 376 return Err(SystemError::EMFILE); 377 } 378 FcntlCommand::GetFd => { 379 // Get file descriptor flags. 380 381 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 382 if FileDescriptorVec::validate_fd(fd) { 383 if let Some(file) = &fds.fds[fd as usize] { 384 if file.close_on_exec() { 385 return Ok(FD_CLOEXEC as usize); 386 } 387 } 388 return Err(SystemError::EBADF); 389 } 390 } 391 return Err(SystemError::EBADF); 392 } 393 FcntlCommand::SetFd => { 394 // Set file descriptor flags. 395 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 396 if FileDescriptorVec::validate_fd(fd) { 397 if let Some(file) = &mut fds.fds[fd as usize] { 398 let arg = arg as u32; 399 if arg & FD_CLOEXEC != 0 { 400 file.set_close_on_exec(true); 401 } else { 402 file.set_close_on_exec(false); 403 } 404 return Ok(0); 405 } 406 return Err(SystemError::EBADF); 407 } 408 } 409 return Err(SystemError::EBADF); 410 } 411 412 FcntlCommand::GetFlags => { 413 // Get file status flags. 414 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 415 if FileDescriptorVec::validate_fd(fd) { 416 if let Some(file) = &fds.fds[fd as usize] { 417 return Ok(file.mode().bits() as usize); 418 } 419 return Err(SystemError::EBADF); 420 } 421 } 422 return Err(SystemError::EBADF); 423 } 424 FcntlCommand::SetFlags => { 425 // Set file status flags. 426 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 427 if FileDescriptorVec::validate_fd(fd) { 428 if let Some(file) = &mut fds.fds[fd as usize] { 429 let arg = arg as u32; 430 let mode = FileMode::from_bits(arg).ok_or(SystemError::EINVAL)?; 431 file.set_mode(mode)?; 432 return Ok(0); 433 } 434 return Err(SystemError::EBADF); 435 } 436 } 437 return Err(SystemError::EBADF); 438 } 439 _ => { 440 // TODO: unimplemented 441 // 未实现的命令,返回0,不报错。 442 443 // kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd); 444 return Ok(0); 445 } 446 } 447 } 448 449 /// # ftruncate 450 /// 451 /// ## 描述 452 /// 453 /// 改变文件大小. 454 /// 如果文件大小大于原来的大小,那么文件的内容将会被扩展到指定的大小,新的空间将会用0填充. 455 /// 如果文件大小小于原来的大小,那么文件的内容将会被截断到指定的大小. 456 /// 457 /// ## 参数 458 /// 459 /// - `fd`:文件描述符 460 /// - `len`:文件大小 461 /// 462 /// ## 返回值 463 /// 464 /// 如果成功,返回0,否则返回错误码. 465 pub fn ftruncate(fd: i32, len: usize) -> Result<usize, SystemError> { 466 if let Some(fds) = FileDescriptorVec::from_pcb(current_pcb()) { 467 if FileDescriptorVec::validate_fd(fd) { 468 if let Some(file) = &mut fds.fds[fd as usize] { 469 let r = file.ftruncate(len).map(|_| 0); 470 return r; 471 } 472 return Err(SystemError::EBADF); 473 } 474 } 475 return Err(SystemError::EBADF); 476 } 477 } 478 479 #[repr(C)] 480 #[derive(Debug, Clone, Copy)] 481 pub struct IoVec { 482 /// 缓冲区的起始地址 483 pub iov_base: *mut u8, 484 /// 缓冲区的长度 485 pub iov_len: usize, 486 } 487 488 /// 用于存储多个来自用户空间的IoVec 489 /// 490 /// 由于目前内核中的文件系统还不支持分散读写,所以暂时只支持将用户空间的IoVec聚合成一个缓冲区,然后进行操作。 491 /// TODO:支持分散读写 492 #[derive(Debug)] 493 pub struct IoVecs(Vec<&'static mut [u8]>); 494 495 impl IoVecs { 496 /// 从用户空间的IoVec中构造IoVecs 497 /// 498 /// @param iov 用户空间的IoVec 499 /// @param iovcnt 用户空间的IoVec的数量 500 /// @param readv 是否为readv系统调用 501 /// 502 /// @return 构造成功返回IoVecs,否则返回错误码 503 pub unsafe fn from_user( 504 iov: *const IoVec, 505 iovcnt: usize, 506 _readv: bool, 507 ) -> Result<Self, SystemError> { 508 // 检查iov指针所在空间是否合法 509 if !verify_area( 510 iov as usize as u64, 511 (iovcnt * core::mem::size_of::<IoVec>()) as u64, 512 ) { 513 return Err(SystemError::EFAULT); 514 } 515 516 // 将用户空间的IoVec转换为引用(注意:这里的引用是静态的,因为用户空间的IoVec不会被释放) 517 let iovs: &[IoVec] = core::slice::from_raw_parts(iov, iovcnt); 518 519 let mut slices: Vec<&mut [u8]> = vec![]; 520 slices.reserve(iovs.len()); 521 522 for iov in iovs.iter() { 523 if iov.iov_len == 0 { 524 continue; 525 } 526 527 if !verify_area(iov.iov_base as usize as u64, iov.iov_len as u64) { 528 return Err(SystemError::EFAULT); 529 } 530 531 slices.push(core::slice::from_raw_parts_mut(iov.iov_base, iov.iov_len)); 532 } 533 534 return Ok(Self(slices)); 535 } 536 537 /// @brief 将IoVecs中的数据聚合到一个缓冲区中 538 /// 539 /// @return 返回聚合后的缓冲区 540 pub fn gather(&self) -> Vec<u8> { 541 let mut buf = Vec::new(); 542 for slice in self.0.iter() { 543 buf.extend_from_slice(slice); 544 } 545 return buf; 546 } 547 548 /// @brief 将给定的数据分散写入到IoVecs中 549 pub fn scatter(&mut self, data: &[u8]) { 550 let mut data: &[u8] = data; 551 for slice in self.0.iter_mut() { 552 let len = core::cmp::min(slice.len(), data.len()); 553 if len == 0 { 554 continue; 555 } 556 557 slice[..len].copy_from_slice(&data[..len]); 558 data = &data[len..]; 559 } 560 } 561 562 /// @brief 创建与IoVecs等长的缓冲区 563 /// 564 /// @param set_len 是否设置返回的Vec的len。 565 /// 如果为true,则返回的Vec的len为所有IoVec的长度之和; 566 /// 否则返回的Vec的len为0,capacity为所有IoVec的长度之和. 567 /// 568 /// @return 返回创建的缓冲区 569 pub fn new_buf(&self, set_len: bool) -> Vec<u8> { 570 let total_len: usize = self.0.iter().map(|slice| slice.len()).sum(); 571 let mut buf: Vec<u8> = Vec::with_capacity(total_len); 572 573 if set_len { 574 unsafe { 575 buf.set_len(total_len); 576 } 577 } 578 return buf; 579 } 580 } 581