From 2052b7021248c58d3f9c8a7ee54d5e078ba5b517 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 25 Apr 2026 13:36:17 +0200 Subject: [PATCH] initfs: Allocate inodes in write_inode --- bootstrap/src/initfs.rs | 2 +- initfs/src/lib.rs | 5 ++-- initfs/src/types.rs | 1 + initfs/tools/src/lib.rs | 39 +++++++++++++++++--------- initfs/tools/tests/archive_and_read.rs | 2 +- 5 files changed, 31 insertions(+), 18 deletions(-) diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 209e771f37..c33918da06 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -135,7 +135,7 @@ impl SchemeSync for InitFsScheme { // filter out double slashes (e.g. /usr//bin/...) .filter(|c| !c.is_empty()); - let mut current_inode = InitFs::ROOT_INODE; + let mut current_inode = self.fs.root_inode(); while let Some(component) = components.next() { match component { diff --git a/initfs/src/lib.rs b/initfs/src/lib.rs index 16e3bc3d23..db7ed8b008 100644 --- a/initfs/src/lib.rs +++ b/initfs/src/lib.rs @@ -268,8 +268,9 @@ impl<'initfs> InitFs<'initfs> { plain::slice_from_bytes::(inode_table_bytes) .expect("expected inode struct alignment to be 1") } - pub const ROOT_INODE: Inode = Inode(0); - + pub fn root_inode(&self) -> Inode { + Inode(self.get_header_assume_valid().root_inode.get()) + } pub fn all_inodes(&self) -> impl Iterator { (0..self.inode_count()).map(Inode) } diff --git a/initfs/src/types.rs b/initfs/src/types.rs index 8ef4a87833..8dce929151 100644 --- a/initfs/src/types.rs +++ b/initfs/src/types.rs @@ -70,6 +70,7 @@ pub struct Header { pub bootstrap_entry: U64, pub initfs_size: U64, pub page_size: U16, + pub root_inode: U16, } const _: () = { diff --git a/initfs/tools/src/lib.rs b/initfs/tools/src/lib.rs index 7b973f2aa3..59d1afd4ab 100644 --- a/initfs/tools/src/lib.rs +++ b/initfs/tools/src/lib.rs @@ -229,12 +229,20 @@ fn allocate_and_write_link(state: &mut State, link: &Path) -> Result u16 { + let inode = *current_inode; + *current_inode += 1; state.inode_table[usize::from(inode)] = Some(initfs::InodeHeader { type_: (ty as u32).into(), length: initfs::Length(write_result.size.into()), offset: initfs::Offset(write_result.offset.into()), }); + inode } fn allocate_and_write_dir( state: &mut State, @@ -293,8 +301,7 @@ fn allocate_and_write_dir( .try_into() .expect("expected dir entry count not to exceed u32"); - *current_inode += 1; - write_inode(state, ty, write_result, *current_inode); + let inode = write_inode(state, ty, write_result, current_inode); let (name_offset, name_len) = { let name_len: u16 = entry.name.len().try_into().context("file name too long")?; @@ -317,13 +324,13 @@ fn allocate_and_write_dir( log::debug!( "Linking inode {} into dir entry index {}, file name `{}`", - current_inode, + inode, index, String::from_utf8_lossy(&entry.name) ); *direntry = initfs::DirEntry { - inode: (*current_inode).into(), + inode: inode.into(), name_len: name_len.into(), name_offset: initfs::Offset(name_offset.into()), }; @@ -343,18 +350,22 @@ fn allocate_and_write_dir( offset: entry_table_offset, }) } -fn allocate_contents(state: &mut State, dir: &Dir) -> Result<()> { - let start_inode = 0; - let mut current_inode = start_inode; +fn allocate_contents(state: &mut State, dir: &Dir) -> Result { + let mut current_inode = 0; let write_result = allocate_and_write_dir(state, dir, &mut current_inode) .context("failed to allocate and write all directories and files")?; - write_inode(state, initfs::InodeType::Dir, write_result, start_inode); + let root_inode = write_inode( + state, + initfs::InodeType::Dir, + write_result, + &mut current_inode, + ); - state.inode_count = current_inode + 1; + state.inode_count = current_inode; - Ok(()) + Ok(root_inode.into()) } fn write_inode_table(state: &mut State) -> Result { @@ -485,8 +496,7 @@ pub fn archive( file: guard, offset: 0, max_size, - // Include root directory. - inode_count: 1, + inode_count: 0, buffer: vec![0_u8; BUFFER_SIZE].into_boxed_slice(), inode_table: [None; 65536], }; @@ -512,7 +522,7 @@ pub fn archive( })?; let bootstrap_entry = elf_entry(&bootstrap_data); - allocate_contents(&mut state, &root)?; + let root_inode = allocate_contents(&mut state, &root)?; let inode_table_offset = write_inode_table(&mut state)?; @@ -543,6 +553,7 @@ pub fn archive( .len() .into(), page_size: PAGE_SIZE.into(), + root_inode, }; write_all_at(&state.file, &header_bytes, header_offset, "writing header") .context("failed to write header")?; diff --git a/initfs/tools/tests/archive_and_read.rs b/initfs/tools/tests/archive_and_read.rs index cdbe505dbb..f32ea0ad3d 100644 --- a/initfs/tools/tests/archive_and_read.rs +++ b/initfs/tools/tests/archive_and_read.rs @@ -86,7 +86,7 @@ fn archive_and_read() -> Result<()> { let filesystem = redox_initfs::InitFs::new(&data, None).context("failed to parse archive header")?; let inode = filesystem - .get_inode(redox_initfs::InitFs::ROOT_INODE) + .get_inode(filesystem.root_inode()) .ok_or_else(|| anyhow!("Failed to get root inode"))?; let tree = build_tree(filesystem, inode)?;