//! Serialized in-memory truncation and live-reader backing protection. use super::*; use os_turkfs_allocation::{Bitmap, Error, TruncateFile}; pub fn run(allocator: &mut memory::FrameAllocator) -> Result<(), &'static str> { let frames_before = allocator.remaining_pages(); let mut bitmap = Bitmap::validate(64, 3, 3 | (1 << 10) | (1 << 20) | (1 << 30)) .map_err(|_| "k1640-bitmap")?; let mut bytes = [0x5a; 1536]; bytes[512..1024].fill(0x6b); bytes[1024..].fill(0x7c); let file = TruncateFile::new([10, 20, 30], 1025, bytes, &bitmap) .map_err(|_| "k1640-file")?; let first = file.reader().map_err(|_| "k1640-first-reader")?; let second = file.reader().map_err(|_| "k1640-second-reader")?; let before = bitmap; if file.truncate(100, &mut bitmap) != Err(Error::Busy) || bitmap != before || file.length() != 1025 || file.block_count() != 3 || file.active_readers() != 2 || first.byte(1024) != Some(0x7c) { return Err("k1640-reader-busy"); } write_line("TURKOS/OS/K1640-TRUNCATE: READERS=2 BUSY=UNCHANGED"); drop(first); if file.truncate(100, &mut bitmap) != Err(Error::Busy) || bitmap != before || file.length() != 1025 || second.byte(1024) != Some(0x7c) { return Err("k1640-last-reader-busy"); } drop(second); if file.active_readers() != 0 { return Err("k1640-reader-close"); } write_line("TURKOS/OS/K1640-TRUNCATE: LAST-READER=CLOSED"); file.truncate(100, &mut bitmap).map_err(|_| "k1640-truncate")?; if file.length() != 100 || file.block_count() != 1 || bitmap.allocated_bits() != 3 | (1 << 10) || bitmap.counts().free != before.counts().free + 2 { return Err("k1640-retirement"); } write_line("TURKOS/OS/K1640-TRUNCATE: SIZE=100 BLOCKS=1 FREED=2"); let reader = file.reader().map_err(|_| "k1640-short-reader")?; if reader.byte(99) != Some(0x5a) || reader.byte(100) != None || reader.byte(1024) != None || reader.byte(usize::MAX) != None || allocator.remaining_pages() != frames_before { return Err("k1640-byte-boundary"); } write_line("TURKOS/OS/K1640-TRUNCATE: BYTE99=5A BYTE100=EOF FRAMES=UNCHANGED"); Ok(()) }