//! Three-level bounded directory walk and cycle rejection guest probe. use super::*; use os_turkfs_directory::{Directory, Error, Kind, Node, NAME_BYTES}; fn node(inode: u64, parent: u64, kind: Kind, name: &[u8]) -> Node { let mut bytes = [0; NAME_BYTES]; bytes[..name.len()].copy_from_slice(name); Node {inode, parent, kind, name_len: name.len() as u8, name: bytes} } fn tree() -> [Node; 4] { [node(1, 0, Kind::Directory, b""), node(2, 1, Kind::Directory, b"a"), node(3, 2, Kind::Directory, b"b"), node(4, 3, Kind::Regular, b"file")] } pub fn run(allocator: &mut memory::FrameAllocator) -> Result<(), &'static str> { let frames_before = allocator.remaining_pages(); let directory = Directory::validate(tree()).map_err(|_| "k1620-valid")?; if directory.node_count() != 4 || directory.lookup(b"/a/b/file").map(|node| node.inode) != Ok(4) || directory.lookup(b"/a/b").map(|node| node.kind) != Ok(Kind::Directory) || directory.lookup(b"/a/b/file/child") != Err(Error::NotDirectory) { return Err("k1620-walk"); } write_line("TURKOS/OS/K1620-DIR: ROOT-A-B-FILE=4"); let mut self_loop = tree(); self_loop[2].parent = 3; if Directory::validate(self_loop) != Err(Error::Loop) { return Err("k1620-self-loop"); } write_line("TURKOS/OS/K1620-DIR: SELF-LOOP=REJECTED"); let mut mutual_loop = tree(); mutual_loop[1].parent = 3; if Directory::validate(mutual_loop) != Err(Error::Loop) { return Err("k1620-mutual-loop"); } write_line("TURKOS/OS/K1620-DIR: MUTUAL-LOOP=REJECTED"); let mut bad_type = tree(); bad_type[1].kind = Kind::Regular; if Directory::validate(bad_type) != Err(Error::NotDirectory) || allocator.remaining_pages() != frames_before { return Err("k1620-type"); } write_line("TURKOS/OS/K1620-DIR: TYPE=REJECTED FRAMES=UNCHANGED"); Ok(()) }