add os[1-8]-ref for os refereces, add guide, add README

This commit is contained in:
Yu Chen
2022-06-27 22:22:44 +08:00
parent 7c1679774c
commit d752a67137
360 changed files with 32863 additions and 1 deletions

169
os6-ref/src/fs/inode.rs Normal file
View File

@@ -0,0 +1,169 @@
use easy_fs::{
EasyFileSystem,
Inode,
};
use crate::drivers::BLOCK_DEVICE;
use crate::sync::UPSafeCell;
use alloc::sync::Arc;
use lazy_static::*;
use bitflags::*;
use alloc::vec::Vec;
use super::File;
use crate::mm::UserBuffer;
/// A wrapper around a filesystem inode
/// to implement File trait atop
pub struct OSInode {
readable: bool,
writable: bool,
inner: UPSafeCell<OSInodeInner>,
}
/// The OS inode inner in 'UPSafeCell'
pub struct OSInodeInner {
offset: usize,
inode: Arc<Inode>,
}
impl OSInode {
/// Construct an OS inode from a inode
pub fn new(
readable: bool,
writable: bool,
inode: Arc<Inode>,
) -> Self {
Self {
readable,
writable,
inner: unsafe { UPSafeCell::new(OSInodeInner {
offset: 0,
inode,
})},
}
}
/// Read all data inside a inode into vector
pub fn read_all(&self) -> Vec<u8> {
let mut inner = self.inner.exclusive_access();
let mut buffer = [0u8; 512];
let mut v: Vec<u8> = Vec::new();
loop {
let len = inner.inode.read_at(inner.offset, &mut buffer);
if len == 0 {
break;
}
inner.offset += len;
v.extend_from_slice(&buffer[..len]);
}
v
}
}
lazy_static! {
/// The root of all inodes, or '/' in short
pub static ref ROOT_INODE: Arc<Inode> = {
let efs = EasyFileSystem::open(BLOCK_DEVICE.clone());
Arc::new(EasyFileSystem::root_inode(&efs))
};
}
/// List all files in the filesystems
pub fn list_apps() {
println!("/**** APPS ****");
for app in ROOT_INODE.ls() {
println!("{}", app);
}
println!("**************/");
}
bitflags! {
/// Flags for opening files
pub struct OpenFlags: u32 {
const RDONLY = 0;
const WRONLY = 1 << 0;
const RDWR = 1 << 1;
const CREATE = 1 << 9;
const TRUNC = 1 << 10;
}
}
impl OpenFlags {
/// Get the current read write permission on an inode
/// does not check validity for simplicity
/// returns (readable, writable)
pub fn read_write(&self) -> (bool, bool) {
if self.is_empty() {
(true, false)
} else if self.contains(Self::WRONLY) {
(false, true)
} else {
(true, true)
}
}
}
/// Open a file by path
pub fn open_file(name: &str, flags: OpenFlags) -> Option<Arc<OSInode>> {
let (readable, writable) = flags.read_write();
if flags.contains(OpenFlags::CREATE) {
if let Some(inode) = ROOT_INODE.find(name) {
// clear size
inode.clear();
Some(Arc::new(OSInode::new(
readable,
writable,
inode,
)))
} else {
// create file
ROOT_INODE.create(name)
.map(|inode| {
Arc::new(OSInode::new(
readable,
writable,
inode,
))
})
}
} else {
ROOT_INODE.find(name)
.map(|inode| {
if flags.contains(OpenFlags::TRUNC) {
inode.clear();
}
Arc::new(OSInode::new(
readable,
writable,
inode
))
})
}
}
impl File for OSInode {
fn readable(&self) -> bool { self.readable }
fn writable(&self) -> bool { self.writable }
fn read(&self, mut buf: UserBuffer) -> usize {
let mut inner = self.inner.exclusive_access();
let mut total_read_size = 0usize;
for slice in buf.buffers.iter_mut() {
let read_size = inner.inode.read_at(inner.offset, *slice);
if read_size == 0 {
break;
}
inner.offset += read_size;
total_read_size += read_size;
}
total_read_size
}
fn write(&self, buf: UserBuffer) -> usize {
let mut inner = self.inner.exclusive_access();
let mut total_write_size = 0usize;
for slice in buf.buffers.iter() {
let write_size = inner.inode.write_at(inner.offset, *slice);
assert_eq!(write_size, slice.len());
inner.offset += write_size;
total_write_size += write_size;
}
total_write_size
}
}

43
os6-ref/src/fs/mod.rs Normal file
View File

@@ -0,0 +1,43 @@
mod stdio;
mod inode;
use crate::mm::UserBuffer;
/// The common abstraction of all IO resources
pub trait File : Send + Sync {
fn readable(&self) -> bool;
fn writable(&self) -> bool;
fn read(&self, buf: UserBuffer) -> usize;
fn write(&self, buf: UserBuffer) -> usize;
}
/// The stat of a inode
#[repr(C)]
#[derive(Debug)]
pub struct Stat {
/// ID of device containing file
pub dev: u64,
/// inode number
pub ino: u64,
/// file type and mode
pub mode: StatMode,
/// number of hard links
pub nlink: u32,
/// unused pad
pad: [u64; 7],
}
bitflags! {
/// The mode of a inode
/// whether a directory or a file
pub struct StatMode: u32 {
const NULL = 0;
/// directory
const DIR = 0o040000;
/// ordinary regular file
const FILE = 0o100000;
}
}
pub use stdio::{Stdin, Stdout};
pub use inode::{OSInode, open_file, OpenFlags, list_apps};

48
os6-ref/src/fs/stdio.rs Normal file
View File

@@ -0,0 +1,48 @@
use super::File;
use crate::mm::{UserBuffer};
use crate::sbi::console_getchar;
use crate::task::suspend_current_and_run_next;
/// The standard input
pub struct Stdin;
/// The standard output
pub struct Stdout;
impl File for Stdin {
fn readable(&self) -> bool { true }
fn writable(&self) -> bool { false }
fn read(&self, mut user_buf: UserBuffer) -> usize {
assert_eq!(user_buf.len(), 1);
// busy loop
let mut c: usize;
loop {
c = console_getchar();
if c == 0 {
suspend_current_and_run_next();
continue;
} else {
break;
}
}
let ch = c as u8;
unsafe { user_buf.buffers[0].as_mut_ptr().write_volatile(ch); }
1
}
fn write(&self, _user_buf: UserBuffer) -> usize {
panic!("Cannot write to stdin!");
}
}
impl File for Stdout {
fn readable(&self) -> bool { false }
fn writable(&self) -> bool { true }
fn read(&self, _user_buf: UserBuffer) -> usize{
panic!("Cannot read from stdout!");
}
fn write(&self, user_buf: UserBuffer) -> usize {
for buffer in user_buf.buffers.iter() {
print!("{}", core::str::from_utf8(*buffer).unwrap());
}
user_buf.len()
}
}