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