You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
154 lines
5.0 KiB
154 lines
5.0 KiB
use clap::{App, Arg};
|
|
use easy_fs::{BlockDevice, EasyFileSystem};
|
|
use std::fs::{read_dir, File, OpenOptions};
|
|
use std::io::{Read, Seek, SeekFrom, Write};
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
|
|
const BLOCK_SZ: usize = 512;
|
|
|
|
struct BlockFile(Mutex<File>);
|
|
|
|
impl BlockDevice for BlockFile {
|
|
fn read_block(&self, block_id: usize, buf: &mut [u8]) {
|
|
let mut file = self.0.lock().unwrap();
|
|
file.seek(SeekFrom::Start((block_id * BLOCK_SZ) as u64))
|
|
.expect("Error when seeking!");
|
|
assert_eq!(file.read(buf).unwrap(), BLOCK_SZ, "Not a complete block!");
|
|
}
|
|
|
|
fn write_block(&self, block_id: usize, buf: &[u8]) {
|
|
let mut file = self.0.lock().unwrap();
|
|
file.seek(SeekFrom::Start((block_id * BLOCK_SZ) as u64))
|
|
.expect("Error when seeking!");
|
|
assert_eq!(file.write(buf).unwrap(), BLOCK_SZ, "Not a complete block!");
|
|
}
|
|
|
|
fn handle_irq(&self) { unimplemented!(); }
|
|
}
|
|
|
|
fn main() {
|
|
easy_fs_pack().expect("Error when packing easy-fs!");
|
|
}
|
|
|
|
fn easy_fs_pack() -> std::io::Result<()> {
|
|
let matches = App::new("EasyFileSystem packer")
|
|
.arg(
|
|
Arg::with_name("source")
|
|
.short("s")
|
|
.long("source")
|
|
.takes_value(true)
|
|
.help("Executable source dir(with backslash)"),
|
|
)
|
|
.arg(
|
|
Arg::with_name("target")
|
|
.short("t")
|
|
.long("target")
|
|
.takes_value(true)
|
|
.help("Executable target dir(with backslash)"),
|
|
)
|
|
.get_matches();
|
|
let src_path = matches.value_of("source").unwrap();
|
|
let target_path = matches.value_of("target").unwrap();
|
|
println!("src_path = {}\ntarget_path = {}", src_path, target_path);
|
|
let block_file = Arc::new(BlockFile(Mutex::new({
|
|
let f = OpenOptions::new()
|
|
.read(true)
|
|
.write(true)
|
|
.create(true)
|
|
.open(format!("{}{}", target_path, "fs.img"))?;
|
|
f.set_len(16 * 2048 * 512).unwrap();
|
|
f
|
|
})));
|
|
// 16MiB, at most 4095 files
|
|
let efs = EasyFileSystem::create(block_file, 16 * 2048, 1);
|
|
let root_inode = Arc::new(EasyFileSystem::root_inode(&efs));
|
|
let apps: Vec<_> = read_dir(src_path)
|
|
.unwrap()
|
|
.into_iter()
|
|
.map(|dir_entry| {
|
|
let mut name_with_ext = dir_entry.unwrap().file_name().into_string().unwrap();
|
|
name_with_ext.drain(name_with_ext.find('.').unwrap()..name_with_ext.len());
|
|
name_with_ext
|
|
})
|
|
.collect();
|
|
for app in apps {
|
|
// load app data from host file system
|
|
let mut host_file = File::open(format!("{}{}", target_path, app)).unwrap();
|
|
let mut all_data: Vec<u8> = Vec::new();
|
|
host_file.read_to_end(&mut all_data).unwrap();
|
|
// create a file in easy-fs
|
|
let inode = root_inode.create(app.as_str()).unwrap();
|
|
// write data to easy-fs
|
|
inode.write_at(0, all_data.as_slice());
|
|
}
|
|
// list apps
|
|
for app in root_inode.ls() {
|
|
println!("{}", app);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[test]
|
|
fn efs_test() -> std::io::Result<()> {
|
|
let block_file = Arc::new(BlockFile(Mutex::new({
|
|
let f = OpenOptions::new()
|
|
.read(true)
|
|
.write(true)
|
|
.create(true)
|
|
.open("target/fs.img")?;
|
|
f.set_len(8192 * 512).unwrap();
|
|
f
|
|
})));
|
|
EasyFileSystem::create(block_file.clone(), 4096, 1);
|
|
let efs = EasyFileSystem::open(block_file.clone());
|
|
let root_inode = EasyFileSystem::root_inode(&efs);
|
|
root_inode.create("filea");
|
|
root_inode.create("fileb");
|
|
for name in root_inode.ls() {
|
|
println!("{}", name);
|
|
}
|
|
let filea = root_inode.find("filea").unwrap();
|
|
let greet_str = "Hello, world!";
|
|
filea.write_at(0, greet_str.as_bytes());
|
|
//let mut buffer = [0u8; 512];
|
|
let mut buffer = [0u8; 233];
|
|
let len = filea.read_at(0, &mut buffer);
|
|
assert_eq!(greet_str, core::str::from_utf8(&buffer[..len]).unwrap(),);
|
|
|
|
let mut random_str_test = |len: usize| {
|
|
filea.clear();
|
|
assert_eq!(filea.read_at(0, &mut buffer), 0,);
|
|
let mut str = String::new();
|
|
use rand;
|
|
// random digit
|
|
for _ in 0..len {
|
|
str.push(char::from('0' as u8 + rand::random::<u8>() % 10));
|
|
}
|
|
filea.write_at(0, str.as_bytes());
|
|
let mut read_buffer = [0u8; 127];
|
|
let mut offset = 0usize;
|
|
let mut read_str = String::new();
|
|
loop {
|
|
let len = filea.read_at(offset, &mut read_buffer);
|
|
if len == 0 {
|
|
break;
|
|
}
|
|
offset += len;
|
|
read_str.push_str(core::str::from_utf8(&read_buffer[..len]).unwrap());
|
|
}
|
|
assert_eq!(str, read_str);
|
|
};
|
|
|
|
random_str_test(4 * BLOCK_SZ);
|
|
random_str_test(8 * BLOCK_SZ + BLOCK_SZ / 2);
|
|
random_str_test(100 * BLOCK_SZ);
|
|
random_str_test(70 * BLOCK_SZ + BLOCK_SZ / 7);
|
|
random_str_test((12 + 128) * BLOCK_SZ);
|
|
random_str_test(400 * BLOCK_SZ);
|
|
random_str_test(1000 * BLOCK_SZ);
|
|
random_str_test(2000 * BLOCK_SZ);
|
|
|
|
Ok(())
|
|
}
|