wasm_vfs/
filesystem.rs

1use std::collections::HashMap;
2use std::sync::{Arc, Mutex};
3use std::io::{Read, Write, Seek, SeekFrom};
4use std::path::PathBuf;
5
6pub type Inode = u64;
7
8// future implementation
9//struct Inode {
10    //number: u64,
11    //size: u64,
12    //permissions: Permissions,
13    //user_id: u32,
14    //group_id: u32,
15    //ctime: SystemTime,
16    //mtime: SystemTime,
17    //atime: SystemTime,
18    // etc.
19//}
20
21pub type FileDescriptor = i32;
22
23#[derive(Debug)]
24pub struct File {
25    pub inode: Inode,
26    pub data: Mutex<Vec<u8>>,
27    pub position: u64,
28    pub path: PathBuf
29}
30
31pub struct OpenFile {
32    pub file: Arc<File>,
33    pub position: u64,
34}
35
36impl Read for OpenFile {
37    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
38        let file_data = &self.file.data.lock().unwrap();
39        let bytes_to_read = std::cmp::min(buf.len(), (file_data.len() - self.position as usize));
40        buf[..bytes_to_read].copy_from_slice(&file_data[self.position as usize..(self.position + bytes_to_read as u64) as usize]);
41        self.position += bytes_to_read as u64;
42        Ok(bytes_to_read)
43    }
44}
45
46impl Write for OpenFile {
47    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
48         let mut file_data = self.file.data.lock().unwrap();
49        let new_size = std::cmp::max(file_data.len(), self.position as usize + buf.len());
50        file_data.resize(new_size, 0);
51        file_data[self.position as usize..self.position as usize + buf.len()]
52            .copy_from_slice(buf);
53        self.position += buf.len() as u64;
54        Ok(buf.len())
55    }
56
57    fn flush(&mut self) -> std::io::Result<()> {
58        Ok(())
59    }
60}
61
62pub struct FileSystem {
63    pub files: HashMap<Inode, Arc<File>>,
64    pub inodes: Inode,
65}
66
67impl FileSystem {
68    pub fn new() -> Self {
69        Self {
70            files: HashMap::new(),
71            inodes: 1,
72        }
73    }
74
75    pub fn lookup_inode(&mut self, path: &PathBuf) -> Option<Inode> {
76        let inode = self.files
77            .iter()
78            .find_map(|(&inode, file)| if file.path == *path { Some(inode) } else { None });
79        if inode == None {
80            return Some(self.create_file(Vec::new()))
81        } else {
82            None
83        }
84    }
85
86    pub fn create_file(&mut self, raw_data: Vec<u8>) -> Inode {
87        let inode = self.inodes;
88        let data = Mutex::new(raw_data);
89        let mut path = PathBuf::new();
90        let mut position = 0;
91        let file = File { inode, data, path, position};
92        self.files.insert(inode, Arc::new(file));
93        self.inodes += 1;
94        inode
95    }
96}
97