block: qcow: Make the qcow image compressor test positional

Convert the qcow image compressor test helper to positional access
instead of the cursor. Test only change.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-07-02 23:06:34 +02:00
committed by Rob Bradford
parent 6be2a52d14
commit 899c2df248

View File

@@ -37,9 +37,9 @@ pub fn decompress_cluster(
#[cfg(test)]
pub(crate) mod unit_tests {
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::io::Write;
use std::os::unix::fs::FileExt;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use flate2::Compression;
use flate2::write::DeflateEncoder;
@@ -68,26 +68,30 @@ pub(crate) mod unit_tests {
/// Compress every allocated cluster in a QCOW2 image file in place.
pub fn compress_allocated_clusters(file: &mut File) {
file.seek(SeekFrom::Start(HEADER_CLUSTER_BITS_OFFSET))
let mut buf4 = [0u8; 4];
file.read_exact_at(&mut buf4, HEADER_CLUSTER_BITS_OFFSET)
.unwrap();
let cluster_bits = file.read_u32::<BigEndian>().unwrap();
let cluster_bits = u32::from_be_bytes(buf4);
let cluster_size = 1u64 << cluster_bits;
file.seek(SeekFrom::Start(HEADER_L1_SIZE_OFFSET)).unwrap();
let l1_size = file.read_u32::<BigEndian>().unwrap();
file.read_exact_at(&mut buf4, HEADER_L1_SIZE_OFFSET)
.unwrap();
let l1_size = u32::from_be_bytes(buf4);
file.seek(SeekFrom::Start(HEADER_L1_TABLE_OFFSET)).unwrap();
let l1_table_offset = file.read_u64::<BigEndian>().unwrap();
let mut buf8 = [0u8; 8];
file.read_exact_at(&mut buf8, HEADER_L1_TABLE_OFFSET)
.unwrap();
let l1_table_offset = u64::from_be_bytes(buf8);
let entries_per_l2 = cluster_size / 8;
let mut append_offset = file.seek(SeekFrom::End(0)).unwrap();
let mut append_offset = file.metadata().unwrap().len();
append_offset = (append_offset + 511) & !511;
for l1_idx in 0..l1_size as u64 {
let l1_entry_offset = l1_table_offset + l1_idx * 8;
file.seek(SeekFrom::Start(l1_entry_offset)).unwrap();
let l1_entry = file.read_u64::<BigEndian>().unwrap();
file.read_exact_at(&mut buf8, l1_entry_offset).unwrap();
let l1_entry = u64::from_be_bytes(buf8);
let l2_table_addr = l1_entry & L1_L2_ADDR_MASK;
if l2_table_addr == 0 {
@@ -96,8 +100,8 @@ pub(crate) mod unit_tests {
for l2_idx in 0..entries_per_l2 {
let l2_entry_offset = l2_table_addr + l2_idx * 8;
file.seek(SeekFrom::Start(l2_entry_offset)).unwrap();
let l2_entry = file.read_u64::<BigEndian>().unwrap();
file.read_exact_at(&mut buf8, l2_entry_offset).unwrap();
let l2_entry = u64::from_be_bytes(buf8);
if l2_entry & CLUSTER_USED_FLAG == 0 || l2_entry & COMPRESSED_FLAG != 0 {
continue;
@@ -109,26 +113,26 @@ pub(crate) mod unit_tests {
}
let mut cluster_data = vec![0u8; cluster_size as usize];
file.seek(SeekFrom::Start(host_cluster_addr)).unwrap();
file.read_exact(&mut cluster_data).unwrap();
file.read_exact_at(&mut cluster_data, host_cluster_addr)
.unwrap();
let mut encoder = DeflateEncoder::new(Vec::new(), Compression::default());
encoder.write_all(&cluster_data).unwrap();
let compressed = encoder.finish().unwrap();
file.seek(SeekFrom::Start(append_offset)).unwrap();
file.write_all(&compressed).unwrap();
file.write_all_at(&compressed, append_offset).unwrap();
let padded_len = (compressed.len() + 511) & !511;
if padded_len > compressed.len() {
let padding = vec![0u8; padded_len - compressed.len()];
file.write_all(&padding).unwrap();
file.write_all_at(&padding, append_offset + compressed.len() as u64)
.unwrap();
}
let new_entry =
make_compressed_l2_entry(append_offset, compressed.len(), cluster_bits);
file.seek(SeekFrom::Start(l2_entry_offset)).unwrap();
file.write_u64::<BigEndian>(new_entry).unwrap();
file.write_all_at(&new_entry.to_be_bytes(), l2_entry_offset)
.unwrap();
append_offset += padded_len as u64;
}