From c611054bbd88cd653080bb31cb8f47a6be6cbabd Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 19:50:00 +0100 Subject: [PATCH 01/10] initfs: Move archive-common package into initfs-tools --- Cargo.lock | 17 +---------------- Cargo.toml | 1 - initfs/Cargo.toml | 7 ------- initfs/archive-common/Cargo.toml | 12 ------------ initfs/tools/Cargo.toml | 2 +- initfs/{ => tools}/data/foo/file-link.txt | 0 initfs/{ => tools}/data/foo/file.txt | 0 initfs/tools/out.img | Bin 0 -> 32771 bytes initfs/tools/src/bin/archive.rs | 2 +- initfs/{archive-common => tools}/src/lib.rs | 0 initfs/{ => tools}/tests/archive_and_read.rs | 8 ++++---- 11 files changed, 7 insertions(+), 42 deletions(-) delete mode 100644 initfs/archive-common/Cargo.toml rename initfs/{ => tools}/data/foo/file-link.txt (100%) rename initfs/{ => tools}/data/foo/file.txt (100%) create mode 100644 initfs/tools/out.img rename initfs/{archive-common => tools}/src/lib.rs (100%) rename initfs/{ => tools}/tests/archive_and_read.rs (93%) diff --git a/Cargo.lock b/Cargo.lock index a470b98b49..756eb376f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,17 +163,6 @@ version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" -[[package]] -name = "archive-common" -version = "0.1.0" -dependencies = [ - "anyhow", - "log", - "pathdiff", - "plain", - "redox-initfs", -] - [[package]] name = "arrayvec" version = "0.7.6" @@ -1750,10 +1739,6 @@ dependencies = [ name = "redox-initfs" version = "0.2.0" dependencies = [ - "anyhow", - "archive-common", - "env_logger", - "log", "plain", ] @@ -1762,10 +1747,10 @@ name = "redox-initfs-tools" version = "0.2.0" dependencies = [ "anyhow", - "archive-common", "clap 4.5.58", "env_logger", "log", + "pathdiff", "plain", "redox-initfs", "twox-hash", diff --git a/Cargo.toml b/Cargo.toml index cd662d6bdc..f087b5a050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "daemon", "init", "initfs", - "initfs/archive-common", "initfs/tools", "ipcd", "logd", diff --git a/initfs/Cargo.toml b/initfs/Cargo.toml index b7a4fb48da..96980c9654 100644 --- a/initfs/Cargo.toml +++ b/initfs/Cargo.toml @@ -14,10 +14,3 @@ plain = "0.2" default = ["std"] std = [] - -[dev-dependencies] -# FIXME remove loggers -anyhow.workspace = true -archive-common = {path = "archive-common"} -env_logger = "0.8" -log.workspace = true diff --git a/initfs/archive-common/Cargo.toml b/initfs/archive-common/Cargo.toml deleted file mode 100644 index 04b681190c..0000000000 --- a/initfs/archive-common/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "archive-common" -version = "0.1.0" -authors = ["4lDO2 <4lDO2@protonmail.com>", "Kamil Koczurek "] -edition = "2021" - -[dependencies] -anyhow.workspace = true -log.workspace = true -pathdiff = "0.2.1" -plain = "0.2" -redox-initfs = {path = ".."} diff --git a/initfs/tools/Cargo.toml b/initfs/tools/Cargo.toml index 8305e5cc36..8c4a263b91 100644 --- a/initfs/tools/Cargo.toml +++ b/initfs/tools/Cargo.toml @@ -21,8 +21,8 @@ anyhow.workspace = true clap = {version = "4", features = ["cargo"]} env_logger = "0.8" log.workspace = true +pathdiff = "0.2.1" plain = "0.2" twox-hash = "1.6" -archive-common = {path = "../archive-common"} redox-initfs = {path = ".."} diff --git a/initfs/data/foo/file-link.txt b/initfs/tools/data/foo/file-link.txt similarity index 100% rename from initfs/data/foo/file-link.txt rename to initfs/tools/data/foo/file-link.txt diff --git a/initfs/data/foo/file.txt b/initfs/tools/data/foo/file.txt similarity index 100% rename from initfs/data/foo/file.txt rename to initfs/tools/data/foo/file.txt diff --git a/initfs/tools/out.img b/initfs/tools/out.img new file mode 100644 index 0000000000000000000000000000000000000000..13de974a37b65852902216aece168769140ed77d GIT binary patch literal 32771 zcmeI)u}#B36adg4LV*xS8R1Hr1SA?tDr$r>06}qtMMw}aB4vhP1cqP@24RNaLr5-@ zB84NpFBiUlXY2d9x;x8v#dyBFsotX(arX65MjhWVygZEce{@$lS4TZU5FkK+009C7 z2oNAZfB*pk`zY|!iQZ8zJT=vSb|S8F^Sa5cJCROu^S;UDYyTDnE}EP(0t5&UAV7cs z0RjXF5FkLHeFEL+My%Rbmx>4wAV7cs0RjXF5FkK+0D;{JbfVtU zSxpwHDi+n?xIIsx5&{GW5FkK+009C72oNAZV3R Result<()> { let matches = Command::new("redox-initfs-ar") diff --git a/initfs/archive-common/src/lib.rs b/initfs/tools/src/lib.rs similarity index 100% rename from initfs/archive-common/src/lib.rs rename to initfs/tools/src/lib.rs diff --git a/initfs/tests/archive_and_read.rs b/initfs/tools/tests/archive_and_read.rs similarity index 93% rename from initfs/tests/archive_and_read.rs rename to initfs/tools/tests/archive_and_read.rs index 00880b878a..1a7d8b5365 100644 --- a/initfs/tests/archive_and_read.rs +++ b/initfs/tools/tests/archive_and_read.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, path::Path}; -use anyhow::{Context, Result, anyhow}; +use anyhow::{anyhow, Context, Result}; use redox_initfs::{InitFs, InodeKind, InodeStruct}; #[derive(Debug, Clone, PartialEq)] @@ -74,13 +74,13 @@ fn build_tree<'a>(fs: InitFs<'a>, inode: InodeStruct<'a>) -> anyhow::Result Result<()> { env_logger::init(); - let args = archive_common::Args { + let args = redox_initfs_tools::Args { destination_path: Path::new("out.img"), source: Path::new("data"), bootstrap_code: None, - max_size: archive_common::DEFAULT_MAX_SIZE, + max_size: redox_initfs_tools::DEFAULT_MAX_SIZE, }; - archive_common::archive(&args).context("failed to archive")?; + redox_initfs_tools::archive(&args).context("failed to archive")?; let data = std::fs::read(args.destination_path).context("failed to read new archive")?; let filesystem = From 223b4972343a501b38d9de4abe466c1cb65706af Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 19:51:03 +0100 Subject: [PATCH 02/10] initfs: Make redox-initfs library unconditionally no_std --- initfs/Cargo.toml | 5 ----- initfs/src/lib.rs | 6 +----- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/initfs/Cargo.toml b/initfs/Cargo.toml index 96980c9654..eecc265518 100644 --- a/initfs/Cargo.toml +++ b/initfs/Cargo.toml @@ -9,8 +9,3 @@ license = "MIT" [dependencies] plain = "0.2" - -[features] -default = ["std"] - -std = [] diff --git a/initfs/src/lib.rs b/initfs/src/lib.rs index 328bbc27bc..b67fb32475 100644 --- a/initfs/src/lib.rs +++ b/initfs/src/lib.rs @@ -2,9 +2,6 @@ //! A super simple initfs, only meant to be loaded into RAM by the bootloader, and then directly be //! read. -#[cfg(any(test, feature = "std"))] -extern crate std; - use core::convert::{TryFrom, TryInto}; pub mod types; @@ -28,8 +25,7 @@ impl core::fmt::Display for Error { } } -#[cfg(any(test, feature = "std"))] -impl std::error::Error for Error {} +impl core::error::Error for Error {} type Result = core::result::Result; From 3e62ff9ec74d22bb00923772feb37eda9ebe53dc Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 19:51:55 +0100 Subject: [PATCH 03/10] initfs: Use CARGO_TARGET_TMPDIR in test --- initfs/.gitignore | 4 ---- initfs/tools/out.img | Bin 32771 -> 0 bytes initfs/tools/tests/archive_and_read.rs | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 initfs/.gitignore delete mode 100644 initfs/tools/out.img diff --git a/initfs/.gitignore b/initfs/.gitignore deleted file mode 100644 index 2b9c6e3e30..0000000000 --- a/initfs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -Cargo.lock -# TODO: Maybe use an OUT_DIR environment variable, or mktemp, rather than -# writing directly to the git repository root? -/out.img diff --git a/initfs/tools/out.img b/initfs/tools/out.img deleted file mode 100644 index 13de974a37b65852902216aece168769140ed77d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32771 zcmeI)u}#B36adg4LV*xS8R1Hr1SA?tDr$r>06}qtMMw}aB4vhP1cqP@24RNaLr5-@ zB84NpFBiUlXY2d9x;x8v#dyBFsotX(arX65MjhWVygZEce{@$lS4TZU5FkK+009C7 z2oNAZfB*pk`zY|!iQZ8zJT=vSb|S8F^Sa5cJCROu^S;UDYyTDnE}EP(0t5&UAV7cs z0RjXF5FkLHeFEL+My%Rbmx>4wAV7cs0RjXF5FkK+0D;{JbfVtU zSxpwHDi+n?xIIsx5&{GW5FkK+009C72oNAZV3R Result<()> { env_logger::init(); let args = redox_initfs_tools::Args { - destination_path: Path::new("out.img"), + destination_path: &Path::new(env!("CARGO_TARGET_TMPDIR")).join("out.img"), source: Path::new("data"), bootstrap_code: None, max_size: redox_initfs_tools::DEFAULT_MAX_SIZE, From edd1c249e9cf475d5b6e7befc6e3757b2cbbc8c7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:00:04 +0100 Subject: [PATCH 04/10] initfs: Remove uid and gid fields for inodes The initfs creation code always puts 0 in them. --- bootstrap/src/initfs.rs | 4 ++-- initfs/src/lib.rs | 6 ------ initfs/src/types.rs | 2 -- initfs/tools/src/bin/dump.rs | 6 ++---- initfs/tools/src/lib.rs | 3 --- 5 files changed, 4 insertions(+), 17 deletions(-) diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 3b6d892dfd..d19c4507dd 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -329,8 +329,8 @@ impl SchemeSync for InitFsScheme { InodeKind::File(_) => MODE_FILE, _ => 0, }; - stat.st_uid = inode.uid(); - stat.st_gid = inode.gid(); + stat.st_uid = 0; + stat.st_gid = 0; stat.st_size = u64::try_from(inode_len(inode)?).unwrap_or(u64::MAX); stat.st_ctime = sec.get(); diff --git a/initfs/src/lib.rs b/initfs/src/lib.rs index b67fb32475..5787eccf8e 100644 --- a/initfs/src/lib.rs +++ b/initfs/src/lib.rs @@ -147,12 +147,6 @@ impl<'initfs> InodeStruct<'initfs> { pub fn mode(&self) -> u16 { (self.inode.type_and_mode.get() & MODE_MASK) as u16 } - pub fn uid(&self) -> u32 { - self.inode.uid.get() - } - pub fn gid(&self) -> u32 { - self.inode.gid.get() - } fn ty(&self) -> Option { let raw = (self.inode.type_and_mode.get() & TYPE_MASK) >> TYPE_SHIFT; diff --git a/initfs/src/types.rs b/initfs/src/types.rs index e1c6cb8936..cd49ef5a8f 100644 --- a/initfs/src/types.rs +++ b/initfs/src/types.rs @@ -87,8 +87,6 @@ pub struct InodeHeader { pub type_and_mode: U32, pub length: U32, pub offset: Offset, - pub uid: U32, - pub gid: U32, } pub const MODE_MASK: u32 = 0xFFF; diff --git a/initfs/tools/src/bin/dump.rs b/initfs/tools/src/bin/dump.rs index aed7496167..b8cfc44f80 100644 --- a/initfs/tools/src/bin/dump.rs +++ b/initfs/tools/src/bin/dump.rs @@ -25,7 +25,7 @@ fn main() -> Result<()> { let bytes = std::fs::read(source).context("failed to read image into memory")?; let initfs = InitFs::new(&bytes, None).context("failed to parse initfs header")?; - dbg!(initfs.header()); + println!("{:#?}", initfs.header()); for inode in initfs.all_inodes() { print!("{:?}: ", inode); @@ -38,10 +38,8 @@ fn main() -> Result<()> { } }; print!( - "mode={:#0o}, uid={}, gid={}, kind=", + "mode={:#0o}, kind=", inode_struct.mode(), - inode_struct.uid(), - inode_struct.gid() ); use redox_initfs::InodeKind; diff --git a/initfs/tools/src/lib.rs b/initfs/tools/src/lib.rs index 117281e7ea..3f11808091 100644 --- a/initfs/tools/src/lib.rs +++ b/initfs/tools/src/lib.rs @@ -258,9 +258,6 @@ fn write_inode( type_and_mode: type_and_mode.into(), length: write_result.size.into(), offset: initfs::Offset(write_result.offset.into()), - - gid: 0.into(), //metadata.gid().into(), - uid: 0.into(), //metadata.uid().into(), }; log::debug!( From f0413aec8e80cb69c9ffc91ea012cb216bdae624 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:06:18 +0100 Subject: [PATCH 05/10] initfs: Fill in st_ino Otherwise ls and other tools will think they have already visited a directory when recursively enumerating all files. --- bootstrap/src/initfs.rs | 1 + initfs/src/lib.rs | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index d19c4507dd..3db98b067f 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -323,6 +323,7 @@ impl SchemeSync for InitFsScheme { let inode = Self::get_inode(&self.fs, handle.inode)?; + stat.st_ino = inode.id(); stat.st_mode = inode.mode() | match inode.kind() { InodeKind::Dir(_) => MODE_DIR, diff --git a/initfs/src/lib.rs b/initfs/src/lib.rs index 5787eccf8e..b004a52f23 100644 --- a/initfs/src/lib.rs +++ b/initfs/src/lib.rs @@ -32,6 +32,7 @@ type Result = core::result::Result; #[derive(Clone, Copy)] pub struct InodeStruct<'initfs> { initfs: InitFs<'initfs>, + inode_id: Inode, inode: &'initfs InodeHeader, } @@ -135,6 +136,9 @@ pub enum InodeKind<'initfs> { } impl<'initfs> InodeStruct<'initfs> { + pub fn id(&self) -> u64 { + self.inode_id.0.into() + } fn data(&self) -> Result<&'initfs [u8]> { let start: usize = self.inode.offset.0.get().try_into().map_err(|_| Error)?; @@ -276,17 +280,11 @@ impl<'initfs> InitFs<'initfs> { pub fn inode_count(&self) -> u16 { self.get_header_assume_valid().inode_count.get() } - pub fn get_inode(&self, inode: Inode) -> Option> { - // NOTE: Even for 16-bit architectures (obviously edge-case, but some bootloaders may - // perhaps use this code), we have already checked that the inode table can fit within - // usize, and the table byte size is always larger than the count. - let inode_usize = inode.0 as usize; - - let inode = self.inode_table().get(inode_usize)?; - + pub fn get_inode(&self, inode_id: Inode) -> Option> { Some(InodeStruct { initfs: *self, - inode, + inode_id, + inode: self.inode_table().get(usize::from(inode_id.0))?, }) } } From fc4b48df673c48b7c3521757ad68df54f92e7330 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:33:59 +0100 Subject: [PATCH 06/10] initfs: Fix stat for symlinks --- bootstrap/src/initfs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 3db98b067f..2ef8dcb21c 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -185,8 +185,9 @@ impl SchemeSync for InitFsScheme { Self::get_inode(&self.fs, current_inode)?.kind(), InodeKind::Link(_) ); + let o_stat_nofollow = flags & O_STAT != 0 && flags & O_NOFOLLOW != 0; let o_symlink = flags & O_SYMLINK != 0; - if is_link && !o_symlink { + if is_link && !o_stat_nofollow && !o_symlink { return Err(Error::new(EXDEV)); } @@ -328,6 +329,7 @@ impl SchemeSync for InitFsScheme { | match inode.kind() { InodeKind::Dir(_) => MODE_DIR, InodeKind::File(_) => MODE_FILE, + InodeKind::Link(_) => MODE_SYMLINK, _ => 0, }; stat.st_uid = 0; From c028c49c55a9dbb378732c035acd6c3485be4670 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:34:31 +0100 Subject: [PATCH 07/10] initfs: Symlinks should be resolved relative to symlink parent --- bootstrap/src/initfs.rs | 8 +------- initfs/tools/src/lib.rs | 10 +++++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/bootstrap/src/initfs.rs b/bootstrap/src/initfs.rs index 2ef8dcb21c..640a1f2636 100644 --- a/bootstrap/src/initfs.rs +++ b/bootstrap/src/initfs.rs @@ -8,7 +8,6 @@ use alloc::string::String; use hashbrown::HashMap; use redox_initfs::{InitFs, Inode, InodeDir, InodeKind, InodeStruct, types::Timespec}; -use redox_path::canonicalize_to_standard; use redox_rt::proc::FdGuard; use redox_scheme::{CallerCtx, OpenResult, RequestKind, scheme::SchemeSync}; @@ -238,12 +237,7 @@ impl SchemeSync for InitFsScheme { InodeKind::Dir(_) => Err(Error::new(EISDIR)), InodeKind::Link(link) => { let link_data = link.data().map_err(|_| Error::new(EIO))?; - let path = core::str::from_utf8(link_data).map_err(|_| Error::new(ENOENT))?; - let cannonical = - canonicalize_to_standard(Some("/"), path).ok_or_else(|| Error::new(ENOENT))?; - let data = cannonical.as_bytes(); - - let src_buf = &data[core::cmp::min(offset, data.len())..]; + let src_buf = &link_data[core::cmp::min(offset, link_data.len())..]; let to_copy = core::cmp::min(src_buf.len(), buffer.len()); buffer[..to_copy].copy_from_slice(&src_buf[..to_copy]); diff --git a/initfs/tools/src/lib.rs b/initfs/tools/src/lib.rs index 3f11808091..238e52a282 100644 --- a/initfs/tools/src/lib.rs +++ b/initfs/tools/src/lib.rs @@ -120,14 +120,14 @@ fn read_directory(state: &mut State, path: &Path, root_path: &Path) -> Result Date: Tue, 17 Feb 2026 20:46:26 +0100 Subject: [PATCH 08/10] initfs: Use fixed modes for inode types This also ensures that the write bit is never set and the execute bit is always set for directories. --- initfs/src/lib.rs | 24 +++++++++++------------- initfs/src/types.rs | 31 ++++++++++++++++++++++--------- initfs/tools/src/bin/dump.rs | 8 +------- initfs/tools/src/lib.rs | 36 +++++++++++++----------------------- 4 files changed, 47 insertions(+), 52 deletions(-) diff --git a/initfs/src/lib.rs b/initfs/src/lib.rs index b004a52f23..befb50ec3f 100644 --- a/initfs/src/lib.rs +++ b/initfs/src/lib.rs @@ -149,26 +149,24 @@ impl<'initfs> InodeStruct<'initfs> { self.initfs.base.get(start..end).ok_or(Error) } pub fn mode(&self) -> u16 { - (self.inode.type_and_mode.get() & MODE_MASK) as u16 + match self.ty() { + Some(InodeType::RegularFile) => 0o444, + Some(InodeType::ExecutableFile) => 0o555, + Some(InodeType::Dir) => 0o555, + Some(InodeType::Link) => 0o777, + None => 0o000, + } } fn ty(&self) -> Option { - let raw = (self.inode.type_and_mode.get() & TYPE_MASK) >> TYPE_SHIFT; - - Some(if raw == InodeType::Dir as u32 { - InodeType::Dir - } else if raw == InodeType::RegularFile as u32 { - InodeType::RegularFile - } else if raw == InodeType::Link as u32 { - InodeType::Link - } else { - return None; - }) + InodeType::try_from(self.inode.type_.get()).ok() } pub fn kind(&self) -> InodeKind<'initfs> { let inner = *self; match self.ty() { Some(InodeType::Dir) => InodeKind::Dir(InodeDir { inner }), - Some(InodeType::RegularFile) => InodeKind::File(InodeFile { inner }), + Some(InodeType::RegularFile | InodeType::ExecutableFile) => { + InodeKind::File(InodeFile { inner }) + } Some(InodeType::Link) => InodeKind::Link(InodeLink { inner }), None => InodeKind::Unknown, } diff --git a/initfs/src/types.rs b/initfs/src/types.rs index cd49ef5a8f..bf09476cb5 100644 --- a/initfs/src/types.rs +++ b/initfs/src/types.rs @@ -84,26 +84,39 @@ const _: () = { #[repr(C, packed)] #[derive(Clone, Copy, Debug)] pub struct InodeHeader { - pub type_and_mode: U32, + pub type_: U32, pub length: U32, pub offset: Offset, } -pub const MODE_MASK: u32 = 0xFFF; -pub const MODE_SHIFT: u8 = 0; - -pub const TYPE_SHIFT: u8 = 28; -pub const TYPE_MASK: u32 = 0xF000_0000; - #[derive(Clone, Copy, Debug)] #[repr(u8)] pub enum InodeType { RegularFile = 0x0, - Dir = 0x1, - Link = 0x2, + ExecutableFile = 0x1, + Dir = 0x2, + Link = 0x3, // All other bit patterns are reserved... for now. } +impl TryFrom for InodeType { + type Error = (); + + fn try_from(value: u32) -> Result { + Ok(if value == InodeType::RegularFile as u32 { + InodeType::RegularFile + } else if value == InodeType::ExecutableFile as u32 { + InodeType::ExecutableFile + } else if value == InodeType::Dir as u32 { + InodeType::Dir + } else if value == InodeType::Link as u32 { + InodeType::Link + } else { + return Err(()); + }) + } +} + #[repr(C, packed)] #[derive(Clone, Copy, Debug)] pub struct DirEntry { diff --git a/initfs/tools/src/bin/dump.rs b/initfs/tools/src/bin/dump.rs index b8cfc44f80..2a211f8d1f 100644 --- a/initfs/tools/src/bin/dump.rs +++ b/initfs/tools/src/bin/dump.rs @@ -3,7 +3,7 @@ use std::{ffi::OsStr, path::Path}; use anyhow::{Context, Result}; use clap::{Arg, Command}; -use redox_initfs::InitFs; +use redox_initfs::{InitFs, InodeKind}; fn main() -> Result<()> { let matches = Command::new("redox-initfs-dump") @@ -37,12 +37,6 @@ fn main() -> Result<()> { continue; } }; - print!( - "mode={:#0o}, kind=", - inode_struct.mode(), - ); - - use redox_initfs::InodeKind; match inode_struct.kind() { InodeKind::Unknown => println!("(unknown)"), diff --git a/initfs/tools/src/lib.rs b/initfs/tools/src/lib.rs index 238e52a282..b8e56971e5 100644 --- a/initfs/tools/src/lib.rs +++ b/initfs/tools/src/lib.rs @@ -4,7 +4,7 @@ use std::io::{prelude::*, SeekFrom}; use std::path::{Path, PathBuf}; use std::os::unix::ffi::OsStrExt; -use std::os::unix::fs::{FileExt, FileTypeExt, MetadataExt}; +use std::os::unix::fs::{FileExt, FileTypeExt, PermissionsExt}; use anyhow::{anyhow, bail, Context, Result}; @@ -238,7 +238,6 @@ fn allocate_and_write_link(state: &mut State, link: &Path) -> Result Result<()> { @@ -246,8 +245,6 @@ fn write_inode( .try_into() .expect("inode header length cannot fit within u32"); - let type_and_mode = ((ty as u32) << initfs::TYPE_SHIFT) | (metadata.mode() & 0xFFF); - // TODO: Use main buffer and write in bulk. let mut inode_buf = [0_u8; std::mem::size_of::()]; @@ -255,7 +252,7 @@ fn write_inode( .expect("expected inode struct to have alignment 1, and buffer size to match"); *inode_hdr = initfs::InodeHeader { - type_and_mode: type_and_mode.into(), + type_: (ty as u32).into(), length: write_result.size.into(), offset: initfs::Offset(write_result.offset.into()), }; @@ -310,7 +307,13 @@ fn allocate_and_write_dir( let write_result = allocate_and_write_file(state, file) .context("failed to copy file into image")?; - (write_result, initfs::InodeType::RegularFile) + let type_ = if entry.metadata.permissions().mode() & 0o100 != 0 { + initfs::InodeType::ExecutableFile + } else { + initfs::InodeType::RegularFile + }; + + (write_result, type_) } EntryKind::Link(ref path) => { @@ -325,7 +328,7 @@ fn allocate_and_write_dir( .expect("expected dir entry count not to exceed u32"); *current_inode += 1; - write_inode(state, ty, &entry.metadata, write_result, *current_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")?; @@ -374,24 +377,14 @@ fn allocate_and_write_dir( offset: entry_table_offset, }) } -fn allocate_contents_and_write_inodes( - state: &mut State, - dir: &Dir, - root_metadata: Metadata, -) -> Result<()> { +fn allocate_contents_and_write_inodes(state: &mut State, dir: &Dir) -> Result<()> { let start_inode = 0; let mut current_inode = start_inode; 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, - &root_metadata, - write_result, - start_inode, - ) + write_inode(state, initfs::InodeType::Dir, write_result, start_inode) } struct OutputImageGuard<'a> { @@ -478,9 +471,6 @@ pub fn archive( }; let root_path = source; - let root_metadata = root_path - .metadata() - .context("failed to obtain metadata for root")?; let root = read_directory(&mut state, root_path, root_path).context("failed to read root")?; log::debug!("there are {} inodes", state.inode_count); @@ -532,7 +522,7 @@ pub fn archive( state.inode_table_offset = inode_table_offset.0.get(); - allocate_contents_and_write_inodes(&mut state, &root, root_metadata)?; + allocate_contents_and_write_inodes(&mut state, &root)?; let current_system_time = std::time::SystemTime::now(); From 7248eda12891384db2058835dbd3322a2f2117ae Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:49:16 +0100 Subject: [PATCH 09/10] initfs: Remove unused function --- initfs/src/types.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/initfs/src/types.rs b/initfs/src/types.rs index bf09476cb5..68cf46fe66 100644 --- a/initfs/src/types.rs +++ b/initfs/src/types.rs @@ -11,14 +11,10 @@ macro_rules! primitive( impl $wrapper { #[inline] - pub const fn get(&self) -> $primitive { + pub const fn get(self) -> $primitive { <$primitive>::from_le_bytes(self.0) } #[inline] - pub fn set(&mut self, primitive: $primitive) { - *self = Self::new(primitive); - } - #[inline] pub const fn new(primitive: $primitive) -> Self { Self(<$primitive>::to_le_bytes(primitive)) } From 200ba82e57b63fce608b53c2a567b27f83260085 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 17 Feb 2026 20:54:02 +0100 Subject: [PATCH 10/10] initfs: Actually use Length newtype --- initfs/src/lib.rs | 3 +-- initfs/src/types.rs | 2 +- initfs/tools/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/initfs/src/lib.rs b/initfs/src/lib.rs index befb50ec3f..16e3bc3d23 100644 --- a/initfs/src/lib.rs +++ b/initfs/src/lib.rs @@ -141,8 +141,7 @@ impl<'initfs> InodeStruct<'initfs> { } fn data(&self) -> Result<&'initfs [u8]> { let start: usize = self.inode.offset.0.get().try_into().map_err(|_| Error)?; - - let length: usize = self.inode.length.get().try_into().map_err(|_| Error)?; + let length: usize = self.inode.length.0.get().try_into().map_err(|_| Error)?; let end = start.checked_add(length).ok_or(Error)?; diff --git a/initfs/src/types.rs b/initfs/src/types.rs index 68cf46fe66..8ef4a87833 100644 --- a/initfs/src/types.rs +++ b/initfs/src/types.rs @@ -81,7 +81,7 @@ const _: () = { #[derive(Clone, Copy, Debug)] pub struct InodeHeader { pub type_: U32, - pub length: U32, + pub length: Length, pub offset: Offset, } diff --git a/initfs/tools/src/lib.rs b/initfs/tools/src/lib.rs index b8e56971e5..00d9791168 100644 --- a/initfs/tools/src/lib.rs +++ b/initfs/tools/src/lib.rs @@ -253,7 +253,7 @@ fn write_inode( *inode_hdr = initfs::InodeHeader { type_: (ty as u32).into(), - length: write_result.size.into(), + length: initfs::Length(write_result.size.into()), offset: initfs::Offset(write_result.offset.into()), };