//! Real fixture bytes retained by in-memory reader guards after unlink. use super::*; use os_turkfs_reader::{BlockReader, Extent, File as DiskFile}; use os_turkfs_open_unlink::{Error, File}; const EXPECTED: &[u8; 64] = b"5ab4d3c0b1612817d6c4335036f9445aead46ff52ff5ae3a00d4245b98582854"; struct Transport<'a>(&'a mut virtio_ro_turkfs::RoDisk); impl BlockReader for Transport<'_> { fn read_block(&mut self, lba: u64, output: &mut [u8; 512]) -> Result<(), ()> { self.0.read(lba, output).map_err(|_| ()) } } fn hash_ok(bytes: &[u8]) -> bool { &turkos_kernel::program_hash::hex_lower(&turkos_kernel::turkfs::file_sha256(bytes)) == EXPECTED } pub fn run(boot: &BootData, allocator: &mut memory::FrameAllocator) -> Result<(), &'static str> { let frames_before = allocator.remaining_pages(); let disk_file = DiskFile::validate([ Extent {first_block: 100, block_count: 1}, Extent {first_block: 104, block_count: 1}, Extent {first_block: 108, block_count: 1}], 1300, 2048) .map_err(|_| "k1655-extents")?; let mut disk = virtio_ro_turkfs::RoDisk::open(boot, allocator, "TURKOS/OS/K1655-GET")?; let mut bytes = [0u8; 1300]; let read = disk_file.read_all(&mut Transport(&mut disk), &mut bytes); disk.close(allocator)?; if read != Ok(1300) || !hash_ok(&bytes) { return Err("k1655-disk-read"); } let file = File::new(b"file", [10, 20, 30], bytes).map_err(|_| "k1655-file")?; let first = file.open(b"file").map_err(|_| "k1655-first")?; let second = file.open(b"file").map_err(|_| "k1655-second")?; let bits = file.ownership().blocks; let mut output = [0xa5; 1301]; if first.read_all(&mut output) != Ok(1300) || output[1300] != 0xa5 || !hash_ok(&output[..1300]) { return Err("k1655-before-hash"); } write_line("TURKOS/OS/K1655-UNLINK: BEFORE-SHA256=5ab4d3c0b1612817d6c4335036f9445aead46ff52ff5ae3a00d4245b98582854"); file.unlink(b"file").map_err(|_| "k1655-unlink")?; if file.lookup(b"file") || !matches!(file.open(b"file"), Err(Error::NotFound)) || file.ownership().readers != 2 || file.ownership().blocks != bits || bits.count_ones() != 3 { return Err("k1655-live-backing"); } write_line("TURKOS/OS/K1655-UNLINK: NAME=ABSENT READERS=2 BLOCKS=3"); if first.read_all(&mut output) != Ok(1300) || !hash_ok(&output[..1300]) { return Err("k1655-after-first"); } drop(first); if file.ownership().readers != 1 || file.ownership().blocks != bits || second.read_all(&mut output) != Ok(1300) || output[1300] != 0xa5 || !hash_ok(&output[..1300]) { return Err("k1655-after-second"); } write_line("TURKOS/OS/K1655-UNLINK: AFTER-SHA256=5ab4d3c0b1612817d6c4335036f9445aead46ff52ff5ae3a00d4245b98582854"); drop(second); if file.ownership().readers != 0 || file.ownership().blocks != 0 || allocator.remaining_pages() != frames_before { return Err("k1655-retire"); } write_line("TURKOS/OS/K1655-UNLINK: LAST-CLOSE=RETIRED FRAMES=UNCHANGED"); Ok(()) }