1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::virtio::{VIRTIO, VirtIO, BSIZE};
use crate::{print, println};
use crate::spinlock::Mutex;
pub struct FsFile {
offset: usize,
sz: usize,
rw_offset: Mutex<(usize, usize)>,
readable: bool,
writable: bool,
}
const HEADER_SIZE: usize = 1024;
const FILE_MAX: usize = 1024;
impl FsFile {
fn get_file_info(virtio: &mut VirtIO, path: &str) -> Option<(usize, usize)> {
for id in 0..FILE_MAX {
let b = virtio.read(1, id as u32);
let sz = unsafe { core::ptr::read(b.data.as_ptr() as *const usize) };
let offset = unsafe { core::ptr::read((b.data.as_ptr() as *const usize).add(1)) };
if sz == 0 {
break;
}
let name_sz = {
let mut i = 16;
loop {
let d = b.data[i];
if d == 0 {
break;
}
i += 1;
if i == b.data.len() { break; }
}
i - 16
};
let u8_slice = unsafe { core::slice::from_raw_parts(b.data.as_ptr().add(16), name_sz) };
let name = core::str::from_utf8(u8_slice).unwrap();
if name == path {
return Some((offset, sz));
}
}
None
}
pub fn open(path: &str, mode: usize) -> Self {
let virtio = VIRTIO();
let (offset, sz) = match Self::get_file_info(virtio, path) {
Some(x) => x,
None => { panic!("{} not found", path); }
};
Self {
offset,
sz,
rw_offset: Mutex::new((0, 0), "file rw offset"),
readable: true,
writable: true,
}
}
pub fn read(&self, content: &mut [u8]) -> i32 {
use crate::info;
if !self.readable { return -1; }
let virtio = VIRTIO();
let read_offset = self.rw_offset.lock().0;
let read_sz = (self.sz - read_offset).min(content.len());
let result = virtio.read(1, ((self.offset + read_offset) / BSIZE) as u32);
for i in 0..read_sz {
content[i] = result.data[i];
}
self.rw_offset.lock().0 = read_offset + read_sz;
return read_sz as i32;
}
pub fn write(&self, content: &[u8]) -> i32 {
if !self.writable { return -1; }
unimplemented!()
}
}
pub mod tests {
use super::*;
pub fn tests() -> &'static [(&'static str, fn())] {
&[
("open", test_open),
("read", test_read),
("read_elf", test_read_elf),
]
}
use crate::{print, println};
pub fn test_open() {
let f = FsFile::open("/test.txt", 0);
}
pub fn test_read() {
let f = FsFile::open("/test.txt", 0);
let mut content = [0; 10];
assert_eq!(f.read(&mut content), 10);
assert_eq!(content, [48, 49, 50, 51, 52, 53, 54, 55, 56, 57]);
}
pub fn test_read_elf() {
let f = FsFile::open("/test1", 0);
let mut content = [0; 1024];
while f.read(&mut content) == 1024 {}
}
}