From cf9ac9ccfd258557db357b9070ef16e379b37d11 Mon Sep 17 00:00:00 2001
From: WangRunji <wangrunji0408@163.com>
Date: Fri, 22 Feb 2019 12:54:42 +0800
Subject: [PATCH] split fs mod

---
 kernel/src/fs.rs        | 174 ----------------------------------------
 kernel/src/fs/device.rs |  47 +++++++++++
 kernel/src/fs/file.rs   |  41 ++++++++++
 kernel/src/fs/mod.rs    |  63 +++++++++++++++
 kernel/src/fs/stdio.rs  |  86 ++++++++++++++++++++
 kernel/src/lib.rs       |   4 +
 6 files changed, 241 insertions(+), 174 deletions(-)
 delete mode 100644 kernel/src/fs.rs
 create mode 100644 kernel/src/fs/device.rs
 create mode 100644 kernel/src/fs/file.rs
 create mode 100644 kernel/src/fs/mod.rs
 create mode 100644 kernel/src/fs/stdio.rs

diff --git a/kernel/src/fs.rs b/kernel/src/fs.rs
deleted file mode 100644
index ffb87e4..0000000
--- a/kernel/src/fs.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-use simple_filesystem::*;
-use alloc::{boxed::Box, sync::Arc, string::String, collections::VecDeque, vec::Vec};
-use core::any::Any;
-use core::ops::Deref;
-use lazy_static::lazy_static;
-#[cfg(target_arch = "x86_64")]
-use crate::arch::driver::ide;
-use crate::sync::Condvar;
-use crate::sync::SpinNoIrqLock as Mutex;
-use crate::drivers::{self, AsAny};
-use crate::drivers::block::virtio_blk::VirtIOBlkDriver;
-
-lazy_static! {
-    pub static ref ROOT_INODE: Arc<INode> = {
-        #[cfg(not(feature = "link_user"))]
-        let device = {
-            #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
-            {
-                Box::new(drivers::DRIVERS.lock().iter()
-                    .map(|device| device.deref().as_any().downcast_ref::<VirtIOBlkDriver>())
-                    .find(|maybe_blk| maybe_blk.is_some())
-                    .expect("VirtIOBlk not found")
-                    .unwrap().clone())
-            }
-            #[cfg(target_arch = "x86_64")]
-            {
-                Box::new(ide::IDE::new(1))
-            }
-        };
-        #[cfg(feature = "link_user")]
-        let device = {
-            extern {
-                fn _user_img_start();
-                fn _user_img_end();
-            }
-            Box::new(unsafe { MemBuf::new(_user_img_start, _user_img_end) })
-        };
-
-        let sfs = SimpleFileSystem::open(device).expect("failed to open SFS");
-        sfs.root_inode()
-    };
-}
-
-#[cfg(not(target_arch = "x86_64"))]
-struct MemBuf(&'static [u8]);
-
-#[cfg(not(target_arch = "x86_64"))]
-impl MemBuf {
-    unsafe fn new(begin: unsafe extern fn(), end: unsafe extern fn()) -> Self {
-        use core::slice;
-        MemBuf(slice::from_raw_parts(begin as *const u8, end as usize - begin as usize))
-    }
-}
-
-#[cfg(not(target_arch = "x86_64"))]
-impl Device for MemBuf {
-    fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option<usize> {
-        let slice = self.0;
-        let len = buf.len().min(slice.len() - offset);
-        buf[..len].copy_from_slice(&slice[offset..offset + len]);
-        Some(len)
-    }
-    fn write_at(&mut self, _offset: usize, _buf: &[u8]) -> Option<usize> {
-        None
-    }
-}
-
-#[cfg(target_arch = "x86_64")]
-impl BlockedDevice for ide::IDE {
-    const BLOCK_SIZE_LOG2: u8 = 9;
-    fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool {
-        use core::slice;
-        assert!(buf.len() >= ide::BLOCK_SIZE);
-        let buf = unsafe { slice::from_raw_parts_mut(buf.as_ptr() as *mut u32, ide::BLOCK_SIZE / 4) };
-        self.read(block_id as u64, 1, buf).is_ok()
-    }
-    fn write_at(&mut self, block_id: usize, buf: &[u8]) -> bool {
-        use core::slice;
-        assert!(buf.len() >= ide::BLOCK_SIZE);
-        let buf = unsafe { slice::from_raw_parts(buf.as_ptr() as *mut u32, ide::BLOCK_SIZE / 4) };
-        self.write(block_id as u64, 1, buf).is_ok()
-    }
-}
-
-#[derive(Default)]
-pub struct Stdin {
-    buf: Mutex<VecDeque<char>>,
-    pushed: Condvar,
-}
-
-impl Stdin {
-    pub fn push(&self, c: char) {
-        self.buf.lock().push_back(c);
-        self.pushed.notify_one();
-    }
-    pub fn pop(&self) -> char {
-        // QEMU v3.0 don't support M-mode external interrupt (bug?)
-        // So we have to use polling.
-        #[cfg(feature = "m_mode")]
-        loop {
-            let c = crate::arch::io::getchar();
-            if c != '\0' { return c; }
-        }
-        #[cfg(not(feature = "m_mode"))]
-        loop {
-            let ret = self.buf.lock().pop_front();
-            match ret {
-                Some(c) => return c,
-                None => self.pushed._wait(),
-            }
-        }
-    }
-}
-
-#[derive(Default)]
-pub struct Stdout;
-
-lazy_static! {
-    pub static ref STDIN: Arc<Stdin> = Arc::new(Stdin::default());
-    pub static ref STDOUT: Arc<Stdout> = Arc::new(Stdout::default());
-}
-
-// TODO: better way to provide default impl?
-macro_rules! impl_inode {
-    () => {
-        fn info(&self) -> Result<FileInfo> { Err(FsError::NotSupported) }
-        fn sync(&self) -> Result<()> { Ok(()) }
-        fn resize(&self, _len: usize) -> Result<()> { Err(FsError::NotSupported) }
-        fn create(&self, _name: &str, _type_: FileType) -> Result<Arc<INode>> { Err(FsError::NotDir) }
-        fn unlink(&self, _name: &str) -> Result<()> { Err(FsError::NotDir) }
-        fn link(&self, _name: &str, _other: &Arc<INode>) -> Result<()> { Err(FsError::NotDir) }
-        fn rename(&self, _old_name: &str, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
-        fn move_(&self, _old_name: &str, _target: &Arc<INode>, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
-        fn find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
-        fn get_entry(&self, _id: usize) -> Result<String> { Err(FsError::NotDir) }
-        fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
-        fn as_any_ref(&self) -> &Any { self }
-    };
-}
-
-impl INode for Stdin {
-    fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
-        buf[0] = self.pop() as u8;
-        Ok(1)
-    }
-    fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> { unimplemented!() }
-    impl_inode!();
-}
-
-impl INode for Stdout {
-    fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> { unimplemented!() }
-    fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
-        use core::str;
-        //we do not care the utf-8 things, we just want to print it!
-        let s = unsafe{ str::from_utf8_unchecked(buf) };
-        print!("{}", s);
-        Ok(buf.len())
-    }
-    impl_inode!();
-}
-
-pub trait INodeExt {
-    fn read_as_vec(&self) -> Result<Vec<u8>>;
-}
-
-impl INodeExt for INode {
-    fn read_as_vec(&self) -> Result<Vec<u8>> {
-        let size = self.info()?.size;
-        let mut buf = Vec::with_capacity(size);
-        unsafe { buf.set_len(size); }
-        self.read_at(0, buf.as_mut_slice())?;
-        Ok(buf)
-    }
-}
diff --git a/kernel/src/fs/device.rs b/kernel/src/fs/device.rs
new file mode 100644
index 0000000..9f0feb3
--- /dev/null
+++ b/kernel/src/fs/device.rs
@@ -0,0 +1,47 @@
+//! Implement Device
+
+use simple_filesystem::*;
+
+#[cfg(target_arch = "x86_64")]
+use crate::arch::driver::ide;
+
+#[cfg(not(target_arch = "x86_64"))]
+pub struct MemBuf(&'static [u8]);
+
+#[cfg(not(target_arch = "x86_64"))]
+impl MemBuf {
+    unsafe fn new(begin: unsafe extern fn(), end: unsafe extern fn()) -> Self {
+        use core::slice;
+        MemBuf(slice::from_raw_parts(begin as *const u8, end as usize - begin as usize))
+    }
+}
+
+#[cfg(not(target_arch = "x86_64"))]
+impl Device for MemBuf {
+    fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option<usize> {
+        let slice = self.0;
+        let len = buf.len().min(slice.len() - offset);
+        buf[..len].copy_from_slice(&slice[offset..offset + len]);
+        Some(len)
+    }
+    fn write_at(&mut self, _offset: usize, _buf: &[u8]) -> Option<usize> {
+        None
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+impl BlockedDevice for ide::IDE {
+    const BLOCK_SIZE_LOG2: u8 = 9;
+    fn read_at(&mut self, block_id: usize, buf: &mut [u8]) -> bool {
+        use core::slice;
+        assert!(buf.len() >= ide::BLOCK_SIZE);
+        let buf = unsafe { slice::from_raw_parts_mut(buf.as_ptr() as *mut u32, ide::BLOCK_SIZE / 4) };
+        self.read(block_id as u64, 1, buf).is_ok()
+    }
+    fn write_at(&mut self, block_id: usize, buf: &[u8]) -> bool {
+        use core::slice;
+        assert!(buf.len() >= ide::BLOCK_SIZE);
+        let buf = unsafe { slice::from_raw_parts(buf.as_ptr() as *mut u32, ide::BLOCK_SIZE / 4) };
+        self.write(block_id as u64, 1, buf).is_ok()
+    }
+}
\ No newline at end of file
diff --git a/kernel/src/fs/file.rs b/kernel/src/fs/file.rs
new file mode 100644
index 0000000..d7d4d4f
--- /dev/null
+++ b/kernel/src/fs/file.rs
@@ -0,0 +1,41 @@
+//! File structure for process
+
+use alloc::{string::String, sync::Arc};
+
+use simple_filesystem::{FileInfo, INode, Result};
+
+#[derive(Clone)]
+pub struct File {
+    inode: Arc<INode>,
+    offset: usize,
+    readable: bool,
+    writable: bool,
+}
+
+impl File {
+    pub fn new(inode: Arc<INode>, readable: bool, writable: bool) -> Self {
+        File { inode, offset: 0, readable, writable }
+    }
+
+    pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
+        assert!(self.readable);
+        let len = self.inode.read_at(self.offset, buf)?;
+        self.offset += len;
+        Ok(len)
+    }
+
+    pub fn write(&mut self, buf: &[u8]) -> Result<usize> {
+        assert!(self.writable);
+        let len = self.inode.write_at(self.offset, buf)?;
+        self.offset += len;
+        Ok(len)
+    }
+
+    pub fn info(&self) -> Result<FileInfo> {
+        self.inode.info()
+    }
+
+    pub fn get_entry(&self, id: usize) -> Result<String> {
+        self.inode.get_entry(id)
+    }
+}
\ No newline at end of file
diff --git a/kernel/src/fs/mod.rs b/kernel/src/fs/mod.rs
new file mode 100644
index 0000000..078bf2e
--- /dev/null
+++ b/kernel/src/fs/mod.rs
@@ -0,0 +1,63 @@
+use alloc::{boxed::Box, collections::VecDeque, string::String, sync::Arc, vec::Vec};
+use core::any::Any;
+use core::ops::Deref;
+
+use simple_filesystem::*;
+
+#[cfg(target_arch = "x86_64")]
+use crate::arch::driver::ide;
+use crate::drivers::{self, AsAny};
+use crate::drivers::block::virtio_blk::VirtIOBlkDriver;
+
+pub use self::file::File;
+pub use self::stdio::{STDIN, STDOUT};
+
+mod file;
+mod stdio;
+mod device;
+
+lazy_static! {
+    /// The root of file system
+    pub static ref ROOT_INODE: Arc<INode> = {
+        #[cfg(not(feature = "link_user"))]
+        let device = {
+            #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
+            {
+                Box::new(drivers::DRIVERS.lock().iter()
+                    .map(|device| device.deref().as_any().downcast_ref::<VirtIOBlkDriver>())
+                    .find(|maybe_blk| maybe_blk.is_some())
+                    .expect("VirtIOBlk not found")
+                    .unwrap().clone())
+            }
+            #[cfg(target_arch = "x86_64")]
+            {
+                Box::new(ide::IDE::new(1))
+            }
+        };
+        #[cfg(feature = "link_user")]
+        let device = {
+            extern {
+                fn _user_img_start();
+                fn _user_img_end();
+            }
+            Box::new(unsafe { device::MemBuf::new(_user_img_start, _user_img_end) })
+        };
+
+        let sfs = SimpleFileSystem::open(device).expect("failed to open SFS");
+        sfs.root_inode()
+    };
+}
+
+pub trait INodeExt {
+    fn read_as_vec(&self) -> Result<Vec<u8>>;
+}
+
+impl INodeExt for INode {
+    fn read_as_vec(&self) -> Result<Vec<u8>> {
+        let size = self.info()?.size;
+        let mut buf = Vec::with_capacity(size);
+        unsafe { buf.set_len(size); }
+        self.read_at(0, buf.as_mut_slice())?;
+        Ok(buf)
+    }
+}
diff --git a/kernel/src/fs/stdio.rs b/kernel/src/fs/stdio.rs
new file mode 100644
index 0000000..022f018
--- /dev/null
+++ b/kernel/src/fs/stdio.rs
@@ -0,0 +1,86 @@
+//! Implement INode for Stdin & Stdout
+
+use alloc::{collections::vec_deque::VecDeque, string::String, sync::Arc};
+use core::any::Any;
+
+use simple_filesystem::*;
+
+use crate::sync::Condvar;
+use crate::sync::SpinNoIrqLock as Mutex;
+
+#[derive(Default)]
+pub struct Stdin {
+    buf: Mutex<VecDeque<char>>,
+    pushed: Condvar,
+}
+
+impl Stdin {
+    pub fn push(&self, c: char) {
+        self.buf.lock().push_back(c);
+        self.pushed.notify_one();
+    }
+    pub fn pop(&self) -> char {
+        // QEMU v3.0 don't support M-mode external interrupt (bug?)
+        // So we have to use polling.
+        #[cfg(feature = "m_mode")]
+            loop {
+            let c = crate::arch::io::getchar();
+            if c != '\0' { return c; }
+        }
+        #[cfg(not(feature = "m_mode"))]
+            loop {
+            let ret = self.buf.lock().pop_front();
+            match ret {
+                Some(c) => return c,
+                None => self.pushed._wait(),
+            }
+        }
+    }
+}
+
+#[derive(Default)]
+pub struct Stdout;
+
+lazy_static! {
+    pub static ref STDIN: Arc<Stdin> = Arc::new(Stdin::default());
+    pub static ref STDOUT: Arc<Stdout> = Arc::new(Stdout::default());
+}
+
+// TODO: better way to provide default impl?
+macro_rules! impl_inode {
+    () => {
+        fn info(&self) -> Result<FileInfo> { Err(FsError::NotSupported) }
+        fn sync(&self) -> Result<()> { Ok(()) }
+        fn resize(&self, _len: usize) -> Result<()> { Err(FsError::NotSupported) }
+        fn create(&self, _name: &str, _type_: FileType) -> Result<Arc<INode>> { Err(FsError::NotDir) }
+        fn unlink(&self, _name: &str) -> Result<()> { Err(FsError::NotDir) }
+        fn link(&self, _name: &str, _other: &Arc<INode>) -> Result<()> { Err(FsError::NotDir) }
+        fn rename(&self, _old_name: &str, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
+        fn move_(&self, _old_name: &str, _target: &Arc<INode>, _new_name: &str) -> Result<()> { Err(FsError::NotDir) }
+        fn find(&self, _name: &str) -> Result<Arc<INode>> { Err(FsError::NotDir) }
+        fn get_entry(&self, _id: usize) -> Result<String> { Err(FsError::NotDir) }
+        fn fs(&self) -> Arc<FileSystem> { unimplemented!() }
+        fn as_any_ref(&self) -> &Any { self }
+    };
+}
+
+impl INode for Stdin {
+    fn read_at(&self, _offset: usize, buf: &mut [u8]) -> Result<usize> {
+        buf[0] = self.pop() as u8;
+        Ok(1)
+    }
+    fn write_at(&self, _offset: usize, _buf: &[u8]) -> Result<usize> { unimplemented!() }
+    impl_inode!();
+}
+
+impl INode for Stdout {
+    fn read_at(&self, _offset: usize, _buf: &mut [u8]) -> Result<usize> { unimplemented!() }
+    fn write_at(&self, _offset: usize, buf: &[u8]) -> Result<usize> {
+        use core::str;
+        //we do not care the utf-8 things, we just want to print it!
+        let s = unsafe{ str::from_utf8_unchecked(buf) };
+        print!("{}", s);
+        Ok(buf.len())
+    }
+    impl_inode!();
+}
\ No newline at end of file
diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs
index 3ea683e..f64e22c 100644
--- a/kernel/src/lib.rs
+++ b/kernel/src/lib.rs
@@ -11,6 +11,10 @@
 // just keep it ...
 #[macro_use]
 extern crate alloc;
+#[macro_use]
+extern crate log;
+#[macro_use]
+extern crate lazy_static;
 
 pub use crate::process::{processor, new_kernel_context};
 use rcore_thread::std_thread as thread;