Skip to main content

os/fs/
inode.rs

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