os/fs/
inode.rs

1use super::File;
2use crate::drivers::BLOCK_DEVICE;
3use crate::mm::UserBuffer;
4use crate::sync::UPSafeCell;
5use alloc::sync::Arc;
6use alloc::vec::Vec;
7use bitflags::*;
8use easy_fs::{EasyFileSystem, Inode};
9use lazy_static::*;
10
11pub struct OSInode {
12    readable: bool,
13    writable: bool,
14    inner: UPSafeCell<OSInodeInner>,
15}
16
17pub struct OSInodeInner {
18    offset: usize,
19    inode: Arc<Inode>,
20}
21
22impl OSInode {
23    pub fn new(readable: bool, writable: bool, inode: Arc<Inode>) -> Self {
24        Self {
25            readable,
26            writable,
27            inner: unsafe { UPSafeCell::new(OSInodeInner { offset: 0, inode }) },
28        }
29    }
30    pub fn read_all(&self) -> Vec<u8> {
31        let mut inner = self.inner.exclusive_access();
32        let mut buffer = [0u8; 512];
33        let mut v: Vec<u8> = Vec::new();
34        loop {
35            let len = inner.inode.read_at(inner.offset, &mut buffer);
36            if len == 0 {
37                break;
38            }
39            inner.offset += len;
40            v.extend_from_slice(&buffer[..len]);
41        }
42        v
43    }
44}
45
46lazy_static! {
47    pub static ref ROOT_INODE: Arc<Inode> = {
48        let efs = EasyFileSystem::open(BLOCK_DEVICE.clone());
49        Arc::new(EasyFileSystem::root_inode(&efs))
50    };
51}
52
53pub fn list_apps() {
54    println!("/**** APPS ****");
55    for app in ROOT_INODE.ls() {
56        println!("{}", app);
57    }
58    println!("**************/")
59}
60
61bitflags! {
62    pub struct OpenFlags: u32 {
63        const RDONLY = 0;
64        const WRONLY = 1 << 0;
65        const RDWR = 1 << 1;
66        const CREATE = 1 << 9;
67        const TRUNC = 1 << 10;
68    }
69}
70
71impl OpenFlags {
72    /// Do not check validity for simplicity
73    /// Return (readable, writable)
74    pub fn read_write(&self) -> (bool, bool) {
75        if self.is_empty() {
76            (true, false)
77        } else if self.contains(Self::WRONLY) {
78            (false, true)
79        } else {
80            (true, true)
81        }
82    }
83}
84
85pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> {
86    let (readable, writable) = flags.read_write();
87    if flags.contains(OpenFlags::CREATE) {
88        if let Some(inode) = ROOT_INODE.find(name) {
89            // clear size
90            inode.clear();
91            Some(Arc::new(OSInode::new(readable, writable, inode)))
92        } else {
93            // create file
94            ROOT_INODE
95                .create(name)
96                .map(|inode| Arc::new(OSInode::new(readable, writable, inode)))
97        }
98    } else {
99        ROOT_INODE.find(name).map(|inode| {
100            if flags.contains(OpenFlags::TRUNC) {
101                inode.clear();
102            }
103            Arc::new(OSInode::new(readable, writable, inode))
104        })
105    }
106}
107
108impl File for OSInode {
109    fn readable(&self) -> bool {
110        self.readable
111    }
112    fn writable(&self) -> bool {
113        self.writable
114    }
115    fn read(&self, mut buf: UserBuffer) -> usize {
116        let mut inner = self.inner.exclusive_access();
117        let mut total_read_size = 0usize;
118        for slice in buf.buffers.iter_mut() {
119            let read_size = inner.inode.read_at(inner.offset, *slice);
120            if read_size == 0 {
121                break;
122            }
123            inner.offset += read_size;
124            total_read_size += read_size;
125        }
126        total_read_size
127    }
128    fn write(&self, buf: UserBuffer) -> usize {
129        let mut inner = self.inner.exclusive_access();
130        let mut total_write_size = 0usize;
131        for slice in buf.buffers.iter() {
132            let write_size = inner.inode.write_at(inner.offset, *slice);
133            assert_eq!(write_size, slice.len());
134            inner.offset += write_size;
135            total_write_size += write_size;
136        }
137        total_write_size
138    }
139}