1use 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::*;
16pub struct OSInode {
19 readable: bool,
20 writable: bool,
21 inner: UPSafeCell<OSInodeInner>,
22}
23pub struct OSInodeInner {
25 offset: usize,
26 inode: Arc<Inode>,
27}
28
29impl OSInode {
30 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 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}
61pub fn list_apps() {
63 println!("/**** APPS ****");
64 for app in ROOT_INODE.ls() {
65 println!("{}", app);
66 }
67 println!("**************/");
68}
69
70bitflags! {
71 pub struct OpenFlags: u32 {
73 const RDONLY = 0;
75 const WRONLY = 1 << 0;
77 const RDWR = 1 << 1;
79 const CREATE = 1 << 9;
81 const TRUNC = 1 << 10;
83 }
84}
85
86impl OpenFlags {
87 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}
99pub 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 inode.clear();
106 Some(Arc::new(OSInode::new(readable, writable, inode)))
107 } else {
108 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}