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 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 inode.clear();
91 Some(Arc::new(OSInode::new(readable, writable, inode)))
92 } else {
93 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}