|
@@ -1,44 +1,11 @@
|
|
|
-use ext4_rs::{Block, BlockDevice, Ext4, BLOCK_SIZE};
|
|
|
+use ext4_rs::{Ext4, InodeMode, OpenFlags, EXT4_ROOT_INO};
|
|
|
use simple_logger::SimpleLogger;
|
|
|
-use std::fs::{File, OpenOptions};
|
|
|
-use std::io::{Read, Seek, SeekFrom, Write};
|
|
|
use std::sync::Arc;
|
|
|
+use block_file::BlockFile;
|
|
|
|
|
|
-#[derive(Debug)]
|
|
|
-pub struct BlockFile(File);
|
|
|
+mod block_file;
|
|
|
|
|
|
-impl BlockFile {
|
|
|
- pub fn new(path: &str) -> Self {
|
|
|
- let file = OpenOptions::new()
|
|
|
- .read(true)
|
|
|
- .write(true)
|
|
|
- .open(path)
|
|
|
- .unwrap();
|
|
|
- Self(file)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-impl BlockDevice for BlockFile {
|
|
|
- fn read_block(&self, block_id: u64) -> Block {
|
|
|
- let mut file = &self.0;
|
|
|
- let mut buffer = [0u8; BLOCK_SIZE];
|
|
|
- // warn!("read_block {}", block_id);
|
|
|
- let _r = file.seek(SeekFrom::Start(block_id * BLOCK_SIZE as u64));
|
|
|
- let _r = file.read_exact(&mut buffer);
|
|
|
- Block::new(block_id, buffer)
|
|
|
- }
|
|
|
-
|
|
|
- fn write_block(&self, block: &Block) {
|
|
|
- let mut file = &self.0;
|
|
|
- // warn!("write_block {}", block.block_id);
|
|
|
- let _r = file.seek(SeekFrom::Start(block.block_id * BLOCK_SIZE as u64));
|
|
|
- let _r = file.write_all(&block.data);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-fn logger_init() {
|
|
|
- SimpleLogger::new().init().unwrap();
|
|
|
-}
|
|
|
+const ROOT_INO: u32 = EXT4_ROOT_INO;
|
|
|
|
|
|
fn make_ext4() {
|
|
|
let _ = std::process::Command::new("rm")
|
|
@@ -59,68 +26,101 @@ fn open_ext4() -> Ext4 {
|
|
|
}
|
|
|
|
|
|
fn mkdir_test(ext4: &mut Ext4) {
|
|
|
- ext4.make_dir("d1").expect("mkdir failed");
|
|
|
- ext4.make_dir("d1/d2").expect("mkdir failed");
|
|
|
- ext4.make_dir("d1/d2/d3").expect("mkdir failed");
|
|
|
- ext4.make_dir("d1/d2/d3/d4").expect("mkdir failed");
|
|
|
- ext4.make_dir("d2").expect("mkdir failed");
|
|
|
- ext4.make_dir("d2/d3").expect("mkdir failed");
|
|
|
- ext4.make_dir("d2/d3/d4").expect("mkdir failed");
|
|
|
- ext4.make_dir("d3").expect("mkdir failed");
|
|
|
+ let dir_mode: InodeMode = InodeMode::DIRECTORY | InodeMode::ALL_RWX;
|
|
|
+ ext4.generic_create(ROOT_INO, "d1", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d1/d2", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d1/d2/d3", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d1/d2/d3/d4", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d2", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d2/d3", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d2/d3/d4", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d3", dir_mode)
|
|
|
+ .expect("mkdir failed");
|
|
|
}
|
|
|
|
|
|
-fn open_test(ext4: &mut Ext4) {
|
|
|
- ext4.open_file("d1/d2/d3/d4/f1", "w+").expect("open failed");
|
|
|
- ext4.open_file("d1/d2/d3/d4/f1", "r").expect("open failed");
|
|
|
- ext4.open_file("d1/d2/d3/d4/f5", "a").expect("open failed");
|
|
|
- ext4.open_file("d2/f4", "w+").expect("open failed");
|
|
|
- ext4.open_file("f1", "w+").expect("open failed");
|
|
|
+fn create_test(ext4: &mut Ext4) {
|
|
|
+ let file_mode: InodeMode = InodeMode::FILE | InodeMode::ALL_RWX;
|
|
|
+ ext4.generic_create(ROOT_INO, "d1/d2/d3/d4/f1", file_mode)
|
|
|
+ .expect("open failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d3/f0", file_mode)
|
|
|
+ .expect("open failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "d3/f1", file_mode)
|
|
|
+ .expect("open failed");
|
|
|
+ ext4.generic_create(ROOT_INO, "f1", file_mode)
|
|
|
+ .expect("open failed");
|
|
|
}
|
|
|
|
|
|
fn read_write_test(ext4: &mut Ext4) {
|
|
|
let wbuffer = "hello world".as_bytes();
|
|
|
- let mut wfile = ext4.open_file("d3/f0", "w+").expect("open failed");
|
|
|
- ext4.write_file(&mut wfile, wbuffer).expect("write failed");
|
|
|
+ let wfile = ext4
|
|
|
+ .generic_open(ROOT_INO, "d3/f0", OpenFlags::O_WRONLY)
|
|
|
+ .expect("open failed");
|
|
|
+ ext4.write(wfile.inode, 0, wbuffer).expect("write failed");
|
|
|
|
|
|
let mut rbuffer = vec![0u8; wbuffer.len()];
|
|
|
- let mut rfile = ext4.open_file("d3/f0", "r").expect("open failed");
|
|
|
- ext4.read_file(&mut rfile, &mut rbuffer)
|
|
|
- .expect("read failed");
|
|
|
+ let rfile = ext4
|
|
|
+ .generic_open(ROOT_INO, "d3/f0", OpenFlags::O_RDONLY)
|
|
|
+ .expect("open failed");
|
|
|
+ ext4.read(wfile.inode, 0, &mut rbuffer).expect("read failed");
|
|
|
|
|
|
assert_eq!(wbuffer, rbuffer);
|
|
|
}
|
|
|
|
|
|
fn large_read_write_test(ext4: &mut Ext4) {
|
|
|
let wbuffer = vec![99u8; 1024 * 1024 * 16];
|
|
|
- let mut wfile = ext4.open_file("d3/f1", "w+").expect("open failed");
|
|
|
- ext4.write_file(&mut wfile, &wbuffer).expect("write failed");
|
|
|
-
|
|
|
- let mut rfile = ext4.open_file("d3/f1", "r").expect("open failed");
|
|
|
+ let wfile = ext4
|
|
|
+ .generic_open(ROOT_INO, "d3/f1", OpenFlags::O_WRONLY)
|
|
|
+ .expect("open failed");
|
|
|
+ ext4.write(wfile.inode, 0, &wbuffer).expect("write failed");
|
|
|
+
|
|
|
+ let rfile = ext4
|
|
|
+ .generic_open(ROOT_INO, "d3/f1", OpenFlags::O_RDONLY)
|
|
|
+ .expect("open failed");
|
|
|
let mut rbuffer = vec![0u8; wbuffer.len()];
|
|
|
- ext4.read_file(&mut rfile, &mut rbuffer)
|
|
|
- .expect("read failed");
|
|
|
+ ext4.read(rfile.inode, 0,&mut rbuffer).expect("read failed");
|
|
|
|
|
|
assert_eq!(wbuffer, rbuffer);
|
|
|
}
|
|
|
|
|
|
fn remove_file_test(ext4: &mut Ext4) {
|
|
|
- ext4.remove_file("d3/f0").expect("remove file failed");
|
|
|
- ext4.open_file("d3/f0", "r").expect_err("open failed");
|
|
|
- ext4.remove_file("d3/f1").expect("remove file failed");
|
|
|
- ext4.open_file("d3/f1", "r").expect_err("open failed");
|
|
|
- ext4.remove_file("f1").expect("remove file failed");
|
|
|
- ext4.open_file("f1", "r").expect_err("open failed");
|
|
|
- ext4.remove_file("d1/not_exist")
|
|
|
+ ext4.generic_remove(ROOT_INO, "d3/f0")
|
|
|
+ .expect("remove file failed");
|
|
|
+ ext4.generic_lookup(ROOT_INO, "d3/f0")
|
|
|
+ .expect_err("file not removed");
|
|
|
+ ext4.generic_remove(ROOT_INO, "d3/f1")
|
|
|
+ .expect("remove file failed");
|
|
|
+ ext4.generic_lookup(ROOT_INO, "d3/f1")
|
|
|
+ .expect_err("file not removed");
|
|
|
+ ext4.generic_remove(ROOT_INO, "f1")
|
|
|
+ .expect("remove file failed");
|
|
|
+ ext4.generic_lookup(ROOT_INO, "f1")
|
|
|
+ .expect_err("file not removed");
|
|
|
+ ext4.generic_remove(ROOT_INO, "d1/not_exist")
|
|
|
.expect_err("remove file failed");
|
|
|
}
|
|
|
|
|
|
fn remove_dir_test(ext4: &mut Ext4) {
|
|
|
- ext4.remove_dir("d2").expect("remove dir failed");
|
|
|
- ext4.open_file("d2/f4", "r").expect_err("open failed");
|
|
|
+ ext4.generic_remove(ROOT_INO, "d2")
|
|
|
+ .expect_err("remove unempty dir");
|
|
|
+ ext4.generic_create(ROOT_INO, "dtmp", InodeMode::DIRECTORY | InodeMode::ALL_RWX)
|
|
|
+ .expect("mkdir failed");
|
|
|
+ ext4.generic_lookup(ROOT_INO, "dtmp")
|
|
|
+ .expect("dir not created");
|
|
|
+ ext4.generic_remove(ROOT_INO, "dtmp")
|
|
|
+ .expect("remove file failed");
|
|
|
+ ext4.generic_lookup(ROOT_INO, "dtmp")
|
|
|
+ .expect_err("dir not removed");
|
|
|
}
|
|
|
|
|
|
fn main() {
|
|
|
- logger_init();
|
|
|
+ SimpleLogger::new().init().unwrap();
|
|
|
log::set_max_level(log::LevelFilter::Off);
|
|
|
make_ext4();
|
|
|
println!("ext4.img created");
|
|
@@ -128,15 +128,14 @@ fn main() {
|
|
|
println!("ext4 opened");
|
|
|
mkdir_test(&mut ext4);
|
|
|
println!("mkdir test done");
|
|
|
- open_test(&mut ext4);
|
|
|
- println!("open test done");
|
|
|
+ create_test(&mut ext4);
|
|
|
+ println!("create test done");
|
|
|
read_write_test(&mut ext4);
|
|
|
println!("read write test done");
|
|
|
large_read_write_test(&mut ext4);
|
|
|
println!("large read write test done");
|
|
|
remove_file_test(&mut ext4);
|
|
|
println!("remove file test done");
|
|
|
- log::set_max_level(log::LevelFilter::Debug);
|
|
|
remove_dir_test(&mut ext4);
|
|
|
println!("remove dir test done");
|
|
|
}
|