mirror of
https://github.com/storytold/craft-anything.git
synced 2026-11-05 20:47:45 +01:00
Preserve sparse ext positions across indirect levels (from #705)
This commit is contained in:
@@ -107,6 +107,8 @@ fn file_block_map(data: &[u8], sb: &Sb, inode_off: u64, flags: u32, nblocks: u64
|
||||
if let Some(ind) = r.u32_le(ib + 48).filter(|&p| p != 0) {
|
||||
read_indirect(data, sb, u64::from(ind), 1, per, &mut logical, &mut map);
|
||||
}
|
||||
// The single-indirect span still occupies its logical blocks when its root is absent.
|
||||
logical = 12 + per;
|
||||
// Double indirect.
|
||||
if let Some(dind) = r.u32_le(ib + 52).filter(|&p| p != 0) {
|
||||
read_indirect(data, sb, u64::from(dind), 2, per, &mut logical, &mut map);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
use craft_anything_formats::fsread::{self, Limits};
|
||||
|
||||
const BS: usize = 1024;
|
||||
const FILE_INODE: usize = 5120 + 10 * 128;
|
||||
|
||||
fn put(data: &mut [u8], at: usize, value: u32) {
|
||||
data[at..at + 4].copy_from_slice(&value.to_le_bytes());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_missing_single_indirect_root_keeps_the_whole_sparse_span() {
|
||||
let mut data = craft_anything_testkit::firmware::ext_image(false);
|
||||
data.resize(14 * BS, 0);
|
||||
put(&mut data, 1024 + 4, 14);
|
||||
data[FILE_INODE + 40..FILE_INODE + 100].fill(0);
|
||||
put(&mut data, FILE_INODE + 4, (269 * BS) as u32);
|
||||
put(&mut data, FILE_INODE + 92, 11);
|
||||
put(&mut data, 11 * BS, 12);
|
||||
put(&mut data, 12 * BS, 13);
|
||||
data[13 * BS..13 * BS + 4].copy_from_slice(b"tail");
|
||||
let image = fsread::extfs::read(&data, &Limits::default());
|
||||
let recovered = image.entries.iter().find(|e| e.path == "hello.txt").unwrap().data.as_ref().unwrap();
|
||||
assert!(recovered[..268 * BS].iter().all(|b| *b == 0));
|
||||
assert_eq!(&recovered[268 * BS..268 * BS + 4], b"tail");
|
||||
assert!(image.complete, "{:?}", image.warnings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_existing_single_indirect_block_keeps_its_original_position() {
|
||||
let mut data = craft_anything_testkit::firmware::ext_image(false);
|
||||
data.resize(12 * BS, 0);
|
||||
put(&mut data, 1024 + 4, 12);
|
||||
data[FILE_INODE + 40..FILE_INODE + 100].fill(0);
|
||||
put(&mut data, FILE_INODE + 4, (13 * BS) as u32);
|
||||
put(&mut data, FILE_INODE + 88, 11);
|
||||
put(&mut data, 11 * BS, 8);
|
||||
let image = fsread::extfs::read(&data, &Limits::default());
|
||||
let recovered = image.entries.iter().find(|e| e.path == "hello.txt").unwrap().data.as_ref().unwrap();
|
||||
assert!(recovered[..12 * BS].iter().all(|b| *b == 0));
|
||||
assert_eq!(&recovered[12 * BS..12 * BS + 22], b"Hello ext filesystem!\n");
|
||||
}
|
||||
Reference in New Issue
Block a user