generated from LearningOS/rust-based-os-comp2023
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from LearningOS/working
Use ref implementation for os8 & fix os8-ref cargo.toml
- Loading branch information
Showing
44 changed files
with
3,938 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
mod stdio; | ||
mod inode; | ||
mod pipe; | ||
|
||
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}; | ||
pub use pipe::{Pipe, make_pipe}; |
Oops, something went wrong.