From 075e416a7be6f2e6ec30222271036beb73aef0d7 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Wed, 23 May 2018 21:56:29 +0800 Subject: [PATCH 1/2] Some code for 'mksfs'. Move 'impl Device for std::fs::File' out of test mod. --- Cargo.toml | 10 ++++++-- src/bin/mksfs.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 30 +++++++++++++++++++++--- src/sfs.rs | 1 - src/tests.rs | 18 -------------- 5 files changed, 96 insertions(+), 24 deletions(-) create mode 100644 src/bin/mksfs.rs diff --git a/Cargo.toml b/Cargo.toml index c64817d..8c256d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,13 +4,18 @@ version = "0.0.1" authors = ["WangRunji "] [lib] +name = "lib" #crate-type = ["staticlib"] +[[bin]] +name = "mksfs" +path = "src/bin/mksfs.rs" +required-features = ["std"] + [profile.dev] panic = 'abort' # prevent `_Unwind_Resume` link error [dependencies] -spin = "0.4" bit-set = { default-features = false, version = "0.5" } # default-features contains 'std' static_assertions = "0.2.5" @@ -19,4 +24,5 @@ bitflags = "1.0" [features] debug_print = [] -ucore = [] \ No newline at end of file +ucore = [] +std = [] \ No newline at end of file diff --git a/src/bin/mksfs.rs b/src/bin/mksfs.rs new file mode 100644 index 0000000..17dc102 --- /dev/null +++ b/src/bin/mksfs.rs @@ -0,0 +1,61 @@ +extern crate lib; + +use std::env; +use std::fs; +use std::io::Read; +use std::path::Path; +use lib::*; + +fn main () { + println!("USAGE: "); + let args: Vec<_> = env::args().collect(); + let cmd = &args[1]; + let dir_path = Path::new(&args[2]); + let img_path = Path::new(&args[3]); + match cmd.as_str() { + "zip" => zip(dir_path, img_path), + "unzip" => unzip(dir_path, img_path), + _ => panic!("Invalid command: {}", cmd), + } +} + +fn zip(path: &Path, img_path: &Path) { + use lib::std_impl; + + let mut img = fs::File::create(img_path) + .expect(format!("Failed to create file: {:?}", img_path).as_str()); + let sfs = SimpleFileSystem::create(Box::new(img), 0x1000000); + let inode = sfs.root_inode(); + zip_dir(path, inode); +} + +fn zip_dir(path: &Path, inode: INodePtr) { + println!("{:?}", path); + let dir = fs::read_dir(path).expect("Failed to open dir"); + for entry in dir { + let entry = entry.unwrap(); + let name_ = entry.file_name(); + let name = name_.to_str().unwrap(); + let type_ = entry.file_type().unwrap(); + if type_.is_file() { + let inode = inode.borrow_mut().create(name, FileType::File) + .expect("Failed to create INode"); + let mut file = fs::File::open(entry.path()) + .expect("Failed to open file"); + let mut buf = Vec::::new(); + file.read_to_end(&mut buf) + .expect("Failed to read file"); + inode.borrow_mut().write_at(0, buf.as_ref()) + .expect("Failed to write image"); + println!("{:?}", entry.path()); + } else if type_.is_dir() { + let inode = inode.borrow_mut().create(name, FileType::Dir) + .expect("Failed to create INode"); + zip_dir(entry.path().as_path(), inode); + } + } +} + +fn unzip(path: &Path, img_path: &Path) { + +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index ffef679..2a504cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,10 +3,9 @@ #![cfg_attr(feature = "ucore", feature(allocator_api, global_allocator, lang_items))] #![no_std] -#[cfg(test)] +#[cfg(any(test, feature = "std"))] #[macro_use] extern crate std; -extern crate spin; #[macro_use] extern crate alloc; extern crate bit_set; @@ -37,4 +36,29 @@ pub use vfs::*; #[cfg(feature = "ucore")] #[global_allocator] -pub static UCORE_ALLOCATOR: c_interface::UcoreAllocator = c_interface::UcoreAllocator{}; \ No newline at end of file +pub static UCORE_ALLOCATOR: c_interface::UcoreAllocator = c_interface::UcoreAllocator{}; + +#[cfg(any(test, feature = "std"))] +pub mod std_impl { + use std::fs::{File, OpenOptions}; + use std::io::{Read, Write, Seek, SeekFrom}; + use super::Device; + + impl Device for File { + fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option { + let offset = offset as u64; + match self.seek(SeekFrom::Start(offset)) { + Ok(real_offset) if real_offset == offset => self.read(buf).ok(), + _ => None, + } + } + + fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option { + let offset = offset as u64; + match self.seek(SeekFrom::Start(offset)) { + Ok(real_offset) if real_offset == offset => self.write(buf).ok(), + _ => None, + } + } + } +} \ No newline at end of file diff --git a/src/sfs.rs b/src/sfs.rs index cbf7c89..dddabef 100644 --- a/src/sfs.rs +++ b/src/sfs.rs @@ -1,4 +1,3 @@ -use spin::Mutex; use bit_set::BitSet; use alloc::{boxed::Box, Vec, BTreeMap, rc::{Rc, Weak}, String}; use core::cell::{RefCell, RefMut}; diff --git a/src/tests.rs b/src/tests.rs index ce19b5a..3772d12 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -8,24 +8,6 @@ use std::rc::Rc; use std::mem::uninitialized; use super::structs::{DiskEntry, AsBuf}; -impl Device for File { - fn read_at(&mut self, offset: usize, buf: &mut [u8]) -> Option { - let offset = offset as u64; - match self.seek(SeekFrom::Start(offset)) { - Ok(real_offset) if real_offset == offset => self.read(buf).ok(), - _ => None, - } - } - - fn write_at(&mut self, offset: usize, buf: &[u8]) -> Option { - let offset = offset as u64; - match self.seek(SeekFrom::Start(offset)) { - Ok(real_offset) if real_offset == offset => self.write(buf).ok(), - _ => None, - } - } -} - fn _open_sample_file() -> Rc { let file = File::open("sfs.img") .expect("failed to open sfs.img"); From 8d111eb80071e80f5880d209e77207021dbdbe67 Mon Sep 17 00:00:00 2001 From: WangRunji Date: Sun, 27 May 2018 22:46:12 +0800 Subject: [PATCH 2/2] Basically finish mksfs. But still bugs. --- src/bin/mksfs.rs | 90 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/src/bin/mksfs.rs b/src/bin/mksfs.rs index 17dc102..a959f42 100644 --- a/src/bin/mksfs.rs +++ b/src/bin/mksfs.rs @@ -2,12 +2,12 @@ extern crate lib; use std::env; use std::fs; -use std::io::Read; +use std::io::{Read, Write, Result}; use std::path::Path; +use std::mem::uninitialized; use lib::*; -fn main () { - println!("USAGE: "); +fn main() -> Result<()> { let args: Vec<_> = env::args().collect(); let cmd = &args[1]; let dir_path = Path::new(&args[2]); @@ -15,47 +15,81 @@ fn main () { match cmd.as_str() { "zip" => zip(dir_path, img_path), "unzip" => unzip(dir_path, img_path), - _ => panic!("Invalid command: {}", cmd), + _ => { + println!("USAGE: "); + panic!("Invalid command: {}", cmd); + }, } } -fn zip(path: &Path, img_path: &Path) { - use lib::std_impl; - - let mut img = fs::File::create(img_path) - .expect(format!("Failed to create file: {:?}", img_path).as_str()); +fn zip(path: &Path, img_path: &Path) -> Result<()> { + let img = fs::OpenOptions::new().read(true).write(true).create(true).open(img_path)?; let sfs = SimpleFileSystem::create(Box::new(img), 0x1000000); let inode = sfs.root_inode(); - zip_dir(path, inode); + zip_dir(path, inode)?; + sfs.sync().expect("Failed to sync"); + Ok(()) } -fn zip_dir(path: &Path, inode: INodePtr) { - println!("{:?}", path); +fn zip_dir(path: &Path, inode: INodePtr) -> Result<()> { let dir = fs::read_dir(path).expect("Failed to open dir"); for entry in dir { - let entry = entry.unwrap(); + let entry = entry?; let name_ = entry.file_name(); let name = name_.to_str().unwrap(); - let type_ = entry.file_type().unwrap(); + let type_ = entry.file_type()?; if type_.is_file() { - let inode = inode.borrow_mut().create(name, FileType::File) - .expect("Failed to create INode"); - let mut file = fs::File::open(entry.path()) - .expect("Failed to open file"); - let mut buf = Vec::::new(); - file.read_to_end(&mut buf) - .expect("Failed to read file"); - inode.borrow_mut().write_at(0, buf.as_ref()) - .expect("Failed to write image"); - println!("{:?}", entry.path()); + let inode = inode.borrow_mut().create(name, FileType::File).expect("Failed to create INode"); + let mut file = fs::File::open(entry.path())?; + inode.borrow_mut().resize(file.metadata().unwrap().len() as usize).expect("Failed to resize INode"); + let mut buf: [u8; 4096] = unsafe { uninitialized() }; + let mut offset = 0usize; + let mut len = 4096; + while len == 4096 { + len = file.read(&mut buf)?; + inode.borrow().write_at(offset, &buf).expect("Failed to write image"); + offset += len; + } } else if type_.is_dir() { - let inode = inode.borrow_mut().create(name, FileType::Dir) - .expect("Failed to create INode"); - zip_dir(entry.path().as_path(), inode); + let inode = inode.borrow_mut().create(name, FileType::Dir).expect("Failed to create INode"); + zip_dir(entry.path().as_path(), inode)?; } } + Ok(()) } -fn unzip(path: &Path, img_path: &Path) { +fn unzip(path: &Path, img_path: &Path) -> Result<()> { + let img = fs::File::open(img_path)?; + let sfs = SimpleFileSystem::open(Box::new(img)).expect("Failed to open sfs"); + let inode = sfs.root_inode(); + fs::create_dir(&path)?; + unzip_dir(path, inode) +} +fn unzip_dir(path: &Path, inode: INodePtr) -> Result<()> { + let files = inode.borrow().list().expect("Failed to list files from INode"); + for name in files.iter().skip(2) { + let inode = inode.borrow().lookup(name.as_str()).expect("Failed to lookup"); + let mut path = path.to_path_buf(); + path.push(name); + let info = inode.borrow().info().expect("Failed to get file info"); + match info.type_ { + FileType::File => { + let mut file = fs::File::create(&path)?; + let mut buf: [u8; 4096] = unsafe { uninitialized() }; + let mut offset = 0usize; + let mut len = 4096; + while len == 4096 { + len = inode.borrow().read_at(offset, buf.as_mut()).expect("Failed to read from INode"); + file.write(&buf[..len])?; + offset += len; + } + } + FileType::Dir => { + fs::create_dir(&path)?; + unzip_dir(path.as_path(), inode)?; + } + } + } + Ok(()) } \ No newline at end of file