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 include::bindings::bindings::{ 8 pt_regs, verify_area, AT_REMOVEDIR, PAGE_2M_SIZE, PAGE_4K_SIZE, PROC_MAX_FD_NUM, SEEK_CUR, SEEK_END, SEEK_MAX, SEEK_SET, 9 }, 10 io::SeekFrom, 11 kerror, syscall::SystemError, 12 }; 13 14 use super::{ 15 core::{do_lseek, do_mkdir, do_open, do_read, do_remove_dir, do_unlink_at, do_write}, 16 file::{File, FileMode}, 17 Dirent, FileType, ROOT_INODE, 18 }; 19 20 /// @brief 打开文件 21 /// 22 /// @param regs->r8 path 文件路径 23 /// @param regs->r9 o_flags 打开文件的标志位 24 /// 25 /// @return u64 文件描述符编号,或者是错误码 26 #[no_mangle] 27 pub extern "C" fn sys_open(regs: &pt_regs) -> u64 { 28 let path: &CStr = unsafe { CStr::from_ptr(regs.r8 as usize as *const c_char) }; 29 let path: Result<&str, core::str::Utf8Error> = path.to_str(); 30 if path.is_err() { 31 return SystemError::EINVAL.to_posix_errno() as u64; 32 } 33 let path: &str = path.unwrap(); 34 let flags = regs.r9; 35 let open_flags: FileMode = FileMode::from_bits_truncate(flags as u32); 36 let r: Result<i32, SystemError> = do_open(path, open_flags); 37 38 if r.is_ok() { 39 return r.unwrap() as u64; 40 } else { 41 return r.unwrap_err().to_posix_errno() as u64; 42 } 43 } 44 45 /// @brief 关闭文件的系统调用函数 46 /// 47 /// @param regs->r8 fd:文件描述符编号 48 #[no_mangle] 49 pub extern "C" fn sys_close(regs: &pt_regs) -> u64 { 50 let fd = regs.r8 as i32; 51 let r: Result<(), SystemError> = current_pcb().drop_fd(fd); 52 53 if r.is_ok() { 54 return 0; 55 } else { 56 return r.unwrap_err().to_posix_errno() as u64; 57 } 58 } 59 60 /// @brief 读取文件的系统调用函数 61 /// 62 /// @param regs->r8 文件描述符编号 63 /// @param regs->r9 输出缓冲区 64 /// @param regs->r10 要读取的长度 65 #[no_mangle] 66 pub extern "C" fn sys_read(regs: &pt_regs) -> u64 { 67 let fd = regs.r8 as i32; 68 let buf_vaddr = regs.r9 as usize; 69 let len = regs.r10 as usize; 70 71 // 判断缓冲区是否来自用户态,进行权限校验 72 if user_mode(regs) && unsafe { !verify_area(buf_vaddr as u64, len as u64) } { 73 // 来自用户态,而buffer在内核态,这样的操作不被允许 74 return SystemError::EPERM.to_posix_errno() as u64; 75 } 76 77 let buf: &mut [u8] = 78 unsafe { core::slice::from_raw_parts_mut::<'static, u8>(buf_vaddr as *mut u8, len) }; 79 80 let r: Result<usize, SystemError> = do_read(fd, buf); 81 82 if r.is_ok() { 83 return r.unwrap() as u64; 84 } else { 85 return r.unwrap_err().to_posix_errno() as u64; 86 } 87 } 88 89 /// @brief 向文件写入数据的系统调用函数 90 /// 91 /// @param regs->r8 文件描述符编号 92 /// @param regs->r9 输入缓冲区 93 /// @param regs->r10 要写入的长度 94 #[no_mangle] 95 pub extern "C" fn sys_write(regs: &pt_regs) -> u64 { 96 let fd = regs.r8 as i32; 97 let buf_vaddr = regs.r9 as usize; 98 let len = regs.r10 as usize; 99 100 // 判断缓冲区是否来自用户态,进行权限校验 101 if user_mode(regs) && unsafe { !verify_area(buf_vaddr as u64, len as u64) } { 102 // 来自用户态,而buffer在内核态,这样的操作不被允许 103 return SystemError::EPERM.to_posix_errno() as u64; 104 } 105 106 let buf: &[u8] = 107 unsafe { core::slice::from_raw_parts::<'static, u8>(buf_vaddr as *mut u8, len) }; 108 109 let r: Result<usize, SystemError> = do_write(fd, buf); 110 111 if r.is_ok() { 112 return r.unwrap() as u64; 113 } else { 114 return r.unwrap_err().to_posix_errno() as u64; 115 } 116 } 117 118 /// @brief 调整文件访问指针位置的系统调用函数 119 /// 120 /// @param regs->r8 文件描述符编号 121 /// @param regs->r9 调整偏移量 122 /// @param regs->r10 调整的模式 123 #[no_mangle] 124 pub extern "C" fn sys_lseek(regs: &pt_regs) -> u64 { 125 let fd = regs.r8 as i32; 126 let offset = regs.r9 as i64; 127 let whence = regs.r10 as u32; 128 129 let w: SeekFrom = match whence { 130 SEEK_SET => SeekFrom::SeekSet(offset), 131 SEEK_CUR => SeekFrom::SeekCurrent(offset), 132 SEEK_END => SeekFrom::SeekEnd(offset), 133 SEEK_MAX => SeekFrom::SeekEnd(0), 134 _ => return SystemError::EINVAL.to_posix_errno() as u64, 135 }; 136 137 let r: Result<usize, SystemError> = do_lseek(fd, w); 138 if r.is_ok() { 139 return r.unwrap() as u64; 140 } else { 141 return r.unwrap_err().to_posix_errno() as u64; 142 } 143 } 144 145 /// @brief 切换工作目录 146 /// 147 /// @param dest_path 目标路径 148 /// 149 /// @return 返回码 描述 150 /// 0 | 成功 151 /// 152 /// EACCESS | 权限不足 153 /// 154 /// ELOOP | 解析path时遇到路径循环 155 /// 156 /// ENAMETOOLONG | 路径名过长 157 /// 158 /// ENOENT | 目标文件或目录不存在 159 /// 160 /// ENODIR | 检索期间发现非目录项 161 /// 162 /// ENOMEM | 系统内存不足 163 /// 164 /// EFAULT | 错误的地址 165 /// 166 /// ENAMETOOLONG | 路径过长 167 #[no_mangle] 168 pub extern "C" fn sys_chdir(regs: &pt_regs) -> u64 { 169 if regs.r8 == 0 { 170 return SystemError::EFAULT.to_posix_errno() as u64; 171 } 172 let ptr = regs.r8 as usize as *const c_char; 173 // 权限校验 174 if ptr.is_null() 175 || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) }) 176 { 177 return SystemError::EINVAL.to_posix_errno() as u64; 178 } 179 180 let dest_path: &CStr = unsafe { CStr::from_ptr(ptr) }; 181 let dest_path: Result<&str, core::str::Utf8Error> = dest_path.to_str(); 182 183 if dest_path.is_err() { 184 return SystemError::EINVAL.to_posix_errno() as u64; 185 } 186 187 let dest_path: &str = dest_path.unwrap(); 188 189 if dest_path.len() == 0 { 190 return SystemError::EINVAL.to_posix_errno() as u64; 191 } else if dest_path.len() >= PAGE_4K_SIZE as usize { 192 return SystemError::ENAMETOOLONG.to_posix_errno() as u64; 193 } 194 195 let path = Box::new(dest_path.clone()); 196 let inode = match ROOT_INODE().lookup(&path) { 197 Err(e) => { 198 kerror!("Change Directory Failed, Error = {:?}", e); 199 return SystemError::ENOENT.to_posix_errno() as u64; 200 } 201 Ok(i) => i, 202 }; 203 204 match inode.metadata() { 205 Err(e) => { 206 kerror!("INode Get MetaData Failed, Error = {:?}", e); 207 return SystemError::ENOENT.to_posix_errno() as u64; 208 } 209 Ok(i) => { 210 if let FileType::Dir = i.file_type { 211 return 0; 212 } else { 213 return SystemError::ENOTDIR.to_posix_errno() as u64; 214 } 215 } 216 } 217 } 218 219 /// @brief 获取目录中的数据 220 /// 221 /// @param fd 文件描述符号 222 /// @return uint64_t dirent的总大小 223 #[no_mangle] 224 pub extern "C" fn sys_getdents(regs: &pt_regs) -> u64 { 225 let fd = regs.r8 as i32; 226 let count = regs.r10 as i64; 227 let dirent = match unsafe { (regs.r9 as usize as *mut Dirent).as_mut() } { 228 None => { 229 return 0; 230 } 231 Some(dirent) => dirent, 232 }; 233 234 if fd < 0 || fd as u32 > PROC_MAX_FD_NUM { 235 return SystemError::EBADF.to_posix_errno() as u64; 236 } 237 238 if count < 0 { 239 return SystemError::EINVAL.to_posix_errno() as u64; 240 } 241 242 // 获取fd 243 let file: &mut File = match current_pcb().get_file_mut_by_fd(fd) { 244 None => { 245 return SystemError::EBADF.to_posix_errno() as u64; 246 } 247 Some(file) => file, 248 }; 249 // kdebug!("file={file:?}"); 250 251 return match file.readdir(dirent) { 252 Err(_) => 0, 253 Ok(len) => len, 254 }; 255 } 256 257 /// @brief 创建文件夹 258 /// 259 /// @param path(r8) 路径 / mode(r9) 模式 260 /// 261 /// @return uint64_t 负数错误码 / 0表示成功 262 #[no_mangle] 263 pub extern "C" fn sys_mkdir(regs: &pt_regs) -> u64 { 264 let ptr = regs.r8 as usize as *const c_char; 265 if ptr.is_null() 266 || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) }) 267 { 268 return SystemError::EINVAL.to_posix_errno() as u64; 269 } 270 let path: &CStr = unsafe { CStr::from_ptr(ptr) }; 271 let path: Result<&str, core::str::Utf8Error> = path.to_str(); 272 let mode = regs.r9; 273 274 if path.is_err() { 275 return SystemError::EINVAL.to_posix_errno() as u64; 276 } 277 278 let path = &path.unwrap().to_string(); 279 if path.trim() == "" { 280 return SystemError::EINVAL.to_posix_errno() as u64; 281 } 282 283 return match do_mkdir(&path.trim(), FileMode::from_bits_truncate(mode as u32)) { 284 Err(err) => { 285 kerror!("Failed in do_mkdir, Error Code = {:#?}", err); 286 err.to_posix_errno() as u64 287 } 288 Ok(_) => 0, 289 }; 290 } 291 292 ///@brief 删除文件夹、取消文件的链接、删除文件的系统调用 293 /// 294 ///@param regs->r8 dfd 进程相对路径基准目录的文件描述符(见fcntl.h) 295 /// 296 ///@param regs->r9 路径名称字符串 297 /// 298 ///@param regs->r10 flag 预留的标志位,暂时未使用,请置为0。 299 /// 300 ///@return uint64_t 错误码 301 #[no_mangle] 302 pub extern "C" fn sys_unlink_at(regs: &pt_regs) -> u64 { 303 let _dfd = regs.r8; 304 let ptr = regs.r9 as usize as *const c_char; 305 if ptr.is_null() 306 || (user_mode(regs) && unsafe { !verify_area(ptr as u64, PAGE_2M_SIZE as u64) }) 307 { 308 return SystemError::EINVAL.to_posix_errno() as u64; 309 } 310 let path: &CStr = unsafe { CStr::from_ptr(ptr) }; 311 let path: Result<&str, core::str::Utf8Error> = path.to_str(); 312 let flag = regs.r10; 313 if path.is_err() { 314 return SystemError::EINVAL.to_posix_errno() as u64; 315 } 316 317 let path = &path.unwrap().to_string(); 318 // kdebug!("sys_unlink_at={path:?}"); 319 if (flag & (!(AT_REMOVEDIR as u64))) != 0_u64 { 320 return SystemError::EINVAL.to_posix_errno() as u64; 321 } 322 323 if (flag & (AT_REMOVEDIR as u64)) > 0 { 324 // kdebug!("rmdir"); 325 match do_remove_dir(&path) { 326 Err(err) => { 327 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 328 return err.to_posix_errno() as u64; 329 } 330 Ok(_) => { 331 return 0; 332 } 333 } 334 } 335 336 // kdebug!("rm"); 337 match do_unlink_at(&path, FileMode::from_bits_truncate(flag as u32)) { 338 Err(err) => { 339 kerror!("Failed to Remove Directory, Error Code = {:?}", err); 340 return err.to_posix_errno() as u64; 341 } 342 Ok(_) => { 343 return 0; 344 } 345 } 346 } 347