1 use core::ffi::{c_char, CStr}; 2 3 use alloc::{boxed::Box, string::ToString}; 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