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