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]
sys_open(regs: &pt_regs) -> u6430 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]
sys_close(regs: &pt_regs) -> u6452 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]
sys_read(regs: &pt_regs) -> u6469 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]
sys_write(regs: &pt_regs) -> u6498 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]
sys_lseek(regs: &pt_regs) -> u64127 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]
sys_chdir(regs: &pt_regs) -> u64171 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]
sys_getdents(regs: &pt_regs) -> u64227 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]
sys_mkdir(regs: &pt_regs) -> u64266 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]
sys_unlink_at(regs: &pt_regs) -> u64305 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
do_dup(oldfd: i32) -> Result<i32, SystemError>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
sys_dup(regs: &pt_regs) -> u64377 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
do_dup2(oldfd: i32, newfd: i32) -> Result<i32, SystemError>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
sys_dup2(regs: &pt_regs) -> u64428 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,否则返回错误码
from_user( iov: *const IoVec, iovcnt: usize, _readv: bool, ) -> Result<Self, SystemError>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 返回聚合后的缓冲区
gather(&self) -> Vec<u8>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中
scatter(&mut self, data: &[u8])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 返回创建的缓冲区
new_buf(&self, set_len: bool) -> Vec<u8>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