kernel_thread/task/
file.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
use alloc::{string::String, sync::Arc};
use flatten_objects::FlattenObjects;
use fs::{file::File, pathbuf::PathBuf};
use libc_core::{
    fcntl::{AT_FDCWD, OpenFlags},
    resource::Rlimit,
};
use spin::Mutex;
use syscalls::Errno;
use vfscore::VfsResult;

use super::Sel4Task;

#[derive(Clone)]
pub struct TaskFileInfo {
    /// 工作目录
    pub work_dir: Arc<Mutex<File>>,
    /// 文件描述符
    pub file_ds: Arc<Mutex<FlattenObjects<Arc<File>, 0x200>>>,
    /// 读写限制
    pub rlimit: Arc<Mutex<Rlimit>>,
}

impl Default for TaskFileInfo {
    fn default() -> Self {
        let file_ds = Arc::new(Mutex::new(FlattenObjects::new()));
        Self {
            work_dir: Arc::new(Mutex::new(File::open("/", OpenFlags::DIRECTORY).unwrap())),
            file_ds,
            rlimit: Arc::new(Mutex::new(Rlimit {
                curr: 150,
                max: 200,
            })),
        }
    }
}

impl Sel4Task {
    /// 根据 dir_fd 打开一个文件
    ///
    /// ## 参数
    /// - `fd` 打开文件所在的文件夹
    /// - `path` 需要打开的文件的路径
    /// - `flags` 打开文件使用的标志
    pub fn fd_open(&self, dirfd: isize, path: *const u8, flags: OpenFlags) -> VfsResult<File> {
        let path = self.fd_resolve(dirfd, path)?;
        File::open(path, flags)
    }

    /// 根据 dir_fd 解析一个文件的真实路径
    ///
    /// ## 参数
    /// - `fd` 文件所在的文件夹
    /// - `path` 文件路径
    pub fn fd_resolve(&self, dirfd: isize, path: *const u8) -> VfsResult<PathBuf> {
        let path_bytes = self.read_cstr(path as _).unwrap();
        let filename = String::from_utf8(path_bytes).unwrap();

        if filename.starts_with("/") {
            Ok(filename.into())
        } else {
            let parent = match dirfd {
                AT_FDCWD => self.file.work_dir.clone(),
                _ => Arc::new(Mutex::new(
                    self.file
                        .file_ds
                        .lock()
                        .get(dirfd as _)
                        .ok_or(Errno::EBADF)?
                        .as_ref()
                        .clone(),
                )),
            };
            Ok(parent.lock().path_buf().join(&filename))
        }
    }
}