Merge branch 'no-mount' into 'master'

Add no_mount option and tidy up flags

See merge request redox-os/installer!62
This commit is contained in:
Jeremy Soller
2025-12-15 12:38:41 -07:00
6 changed files with 189 additions and 46 deletions
+1 -1
View File
@@ -22,4 +22,4 @@ cargo-test:
- cargo build --locked
- cargo test
- fallocate -l 256MiB test.bin
- ./target/debug/redox_installer -c res/test.toml test.bin
- ./target/debug/redox_installer -c res/test.toml test.bin --no-mount
+54 -11
View File
@@ -16,8 +16,6 @@ filesystem_size = 256
[packages.coreutils]
[packages.drivers]
[packages.extrautils]
[packages.findutils]
@@ -26,6 +24,8 @@ filesystem_size = 256
[packages.kernel]
[packages.kibi]
[packages.libgcc]
[packages.libstdcxx]
@@ -38,8 +38,6 @@ filesystem_size = 256
[packages.relibc]
[packages.smith]
[packages.userutils]
[packages.uutils]
@@ -48,16 +46,17 @@ filesystem_size = 256
path = "/usr/lib/init.d/00_base"
data = """
# clear and recreate tmpdir with 0o1777 permission
rm -r /tmp
rm -rf /tmp
mkdir -m a=rwxt /tmp
ipcd
ptyd
sudo --daemon
nowait sudo --daemon
"""
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/lib/init.d/00_drivers"
@@ -67,6 +66,7 @@ pcid-spawner /etc/pcid.d/
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/hostname"
@@ -74,6 +74,7 @@ data = "redox"
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/lib/os-release"
@@ -91,6 +92,7 @@ SUPPORT_URL="https://redox-os.org/community/"
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/os-release"
@@ -98,6 +100,7 @@ data = "../usr/lib/os-release"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/pkg.d/50_redox"
@@ -105,6 +108,7 @@ data = "https://static.redox-os.org/pkg"
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr"
@@ -113,6 +117,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/bin"
@@ -121,6 +126,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/bin"
@@ -128,6 +134,7 @@ data = "usr/bin"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/include"
@@ -136,6 +143,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/include"
@@ -143,6 +151,7 @@ data = "usr/include"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/lib"
@@ -151,6 +160,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/lib"
@@ -158,6 +168,7 @@ data = "usr/lib"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/libexec"
@@ -166,6 +177,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/share"
@@ -174,6 +186,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/share"
@@ -181,6 +194,7 @@ data = "usr/share"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/share/fonts"
@@ -188,6 +202,7 @@ data = "../../ui/fonts"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/var"
@@ -196,6 +211,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/var/cache"
@@ -204,6 +220,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/var/lib"
@@ -212,6 +229,7 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/var/lock"
@@ -220,6 +238,7 @@ symlink = false
directory = true
mode = 1023
recursive_chown = false
postinstall = false
[[files]]
path = "/var/log"
@@ -228,6 +247,16 @@ symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/var/run"
data = ""
symlink = false
directory = true
mode = 493
recursive_chown = false
postinstall = false
[[files]]
path = "/var/tmp"
@@ -236,6 +265,7 @@ symlink = false
directory = true
mode = 1023
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/null"
@@ -243,6 +273,7 @@ data = "/scheme/null"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/random"
@@ -250,6 +281,7 @@ data = "/scheme/rand"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/urandom"
@@ -257,6 +289,7 @@ data = "/scheme/rand"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/zero"
@@ -264,6 +297,7 @@ data = "/scheme/zero"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/tty"
@@ -271,6 +305,7 @@ data = "libc:tty"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/stdin"
@@ -278,6 +313,7 @@ data = "libc:stdin"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/stdout"
@@ -285,6 +321,7 @@ data = "libc:stdout"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/dev/stderr"
@@ -292,26 +329,28 @@ data = "libc:stderr"
symlink = true
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/lib/init.d/10_net"
data = """
smolnetd
dnsd
dhcpd -b
nowait dhcpd
"""
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/net/dns"
data = """
208.67.222.222
9.9.9.9
"""
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/net/ip"
@@ -321,6 +360,7 @@ data = """
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/net/ip_router"
@@ -330,6 +370,7 @@ data = """
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/etc/net/ip_subnet"
@@ -339,17 +380,19 @@ data = """
symlink = false
directory = false
recursive_chown = false
postinstall = false
[[files]]
path = "/usr/lib/init.d/30_console"
data = """
inputd -A 2
getty 2
getty /scheme/debug -J
nowait getty 2
nowait getty /scheme/debug -J
"""
symlink = false
directory = false
recursive_chown = false
postinstall = false
[users.root]
password = "password"
+1 -1
View File
@@ -15,7 +15,7 @@ fi
set -x
# Update res/test.toml from the redoxer.toml template
cargo run --release --manifest-path "${RES_PATH}/../Cargo.toml" -- \
"${REDOX_PATH}/build/fstools/bin/redox_installer" \
--config="${REDOX_PATH}/config/x86_64/minimal-net.toml" \
--output-config="${RES_PATH}/test.toml"
sed -i '1s/^/# Automatically generated by update.sh\n\n/' "${RES_PATH}/test.toml"
+17 -8
View File
@@ -19,7 +19,8 @@ fn main() {
.add_flag(&["filesystem-size"])
.add_flag(&["r", "repo-binary"])
.add_flag(&["l", "list-packages"])
.add_flag(&["live"]);
.add_flag(&["live"])
.add_flag(&["no-mount"]);
parser.parse(env::args());
// Use pre-built binaries for packages as the default.
@@ -127,14 +128,22 @@ fn main() {
None
};
if cookbook.is_some() {
config.general.cookbook = cookbook;
}
if parser.found("live") {
config.general.live_disk = Some(true);
}
if parser.found("no-mount") {
config.general.no_mount = Some(true);
}
let write_bootloader = parser.get_opt("write-bootloader");
if write_bootloader.is_some() {
config.general.write_bootloader = write_bootloader;
}
if let Some(path) = parser.args.first() {
if let Err(err) = redox_installer::install(
config,
path,
cookbook.as_deref(),
parser.found("live"),
parser.get_opt("write-bootloader").as_deref(),
) {
if let Err(err) = redox_installer::install(config, path) {
eprintln!("installer: failed to install: {}", err);
process::exit(1);
}
+31 -3
View File
@@ -1,19 +1,47 @@
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
pub struct GeneralConfig {
/// Specify a path where cookbook exists, all packages will be installed locally
pub cookbook: Option<String>,
/// Allow prompts for missing information such as user password, true by default
pub prompt: Option<bool>,
// Allow config to specify cookbook recipe or binary package as default
/// Allow config to specify cookbook recipe or binary package as default
/// note: Not read by installer anymore, exists only for legacy reasons
pub repo_binary: Option<bool>,
pub filesystem_size: Option<u32>, //MiB
pub efi_partition_size: Option<u32>, //MiB
/// Total filesystem size in MB
pub filesystem_size: Option<u32>,
/// EFI partition size in MB, default to 2MB
pub efi_partition_size: Option<u32>,
/// Skip disk partitioning, assume whole disk is a partition
pub skip_partitions: Option<bool>,
/// Set a plain text password to encrypt the disk, or empty string to prompt
pub encrypt_disk: Option<String>,
/// Use live disk for bootloader config, default is false
pub live_disk: Option<bool>,
/// If set, write bootloader disk into this path
pub write_bootloader: Option<String>,
/// Use AR to write files instead of FUSE-based mount
/// (bypasses FUSE, but slower and requires namespaced context such as "podman unshare")
pub no_mount: Option<bool>,
}
impl GeneralConfig {
/// Merge two config, "other" is more dominant
pub(super) fn merge(&mut self, other: GeneralConfig) {
if let Some(cookbook) = other.cookbook {
self.cookbook = Some(cookbook);
}
self.prompt = other.prompt.or(self.prompt);
self.repo_binary = other.repo_binary.or(self.repo_binary);
self.filesystem_size = other.filesystem_size.or(self.filesystem_size);
self.efi_partition_size = other.efi_partition_size.or(self.efi_partition_size);
self.skip_partitions = other.skip_partitions.or(self.skip_partitions);
if let Some(encrypt_disk) = other.encrypt_disk {
self.encrypt_disk = Some(encrypt_disk);
}
self.live_disk = other.live_disk.or(self.live_disk);
if let Some(write_bootloader) = other.write_bootloader {
self.write_bootloader = Some(write_bootloader);
}
self.no_mount = other.no_mount.or(self.no_mount);
}
}
+85 -22
View File
@@ -3,7 +3,7 @@ use anyhow::{anyhow, Context};
use anyhow::{bail, Result};
use pkg::Library;
use rand::{rngs::OsRng, TryRngCore};
use redoxfs::{unmount_path, Disk, DiskIo, FileSystem};
use redoxfs::{unmount_path, Disk, DiskIo, FileSystem, BLOCK_SIZE};
use termion::input::TermRead;
use crate::config::file::FileConfig;
@@ -412,6 +412,67 @@ where
res
}
pub fn with_redoxfs_ar<D, T, F>(mut fs: FileSystem<D>, callback: F) -> Result<T>
where
D: Disk + Send + 'static,
F: FnOnce(&Path) -> Result<T>,
{
let mount_path = if cfg!(target_os = "redox") {
format!("file.redox_installer_{}", process::id())
} else {
format!("/tmp/redox_installer_{}", process::id())
};
let res = callback(Path::new(&mount_path));
if res.is_ok() {
let _end_block = fs
.tx(|tx| {
// Archive_at root node
redoxfs::archive_at(tx, Path::new(&mount_path), redoxfs::TreePtr::root())
.map_err(|err| syscall::Error::new(err.raw_os_error().unwrap()))?;
// Squash alloc log
tx.sync(true)?;
let end_block = tx.header.size() / BLOCK_SIZE;
/* TODO: Cut off any free blocks at the end of the filesystem
let mut end_changed = true;
while end_changed {
end_changed = false;
let allocator = fs.allocator();
let levels = allocator.levels();
for level in 0..levels.len() {
let level_size = 1 << level;
for &block in levels[level].iter() {
if block < end_block && block + level_size >= end_block {
end_block = block;
end_changed = true;
}
}
}
}
*/
// Update header
tx.header.size = (end_block * BLOCK_SIZE).into();
tx.header_changed = true;
tx.sync(false)?;
Ok(end_block)
})
.map_err(syscall_error)?;
// let size = (fs.block + end_block) * BLOCK_SIZE;
// fs.disk.file.set_len(size)?;
}
fs::remove_dir_all(&mount_path)?;
res
}
pub fn fetch_bootloaders(
config: &Config,
cookbook: Option<&str>,
@@ -744,42 +805,44 @@ pub fn try_fast_install<D: redoxfs::Disk, F: FnMut(u64, u64)>(
Ok(true)
}
fn install_inner(
config: Config,
output: &Path,
cookbook: Option<&str>,
live: bool,
write_bootloader: Option<&str>,
) -> Result<()> {
fn install_inner(config: Config, output: &Path) -> Result<()> {
println!("Install {config:#?} to {}", output.display());
let cookbook = config.general.cookbook.clone();
let cookbook = cookbook.as_ref().map(|p| p.as_str());
if output.is_dir() {
install_dir(config, output, cookbook)
} else {
let live = config.general.live_disk.unwrap_or(false);
let password_opt = config.general.encrypt_disk.clone();
let password_opt = password_opt.as_ref().map(|p| p.as_bytes());
let (bootloader_bios, bootloader_efi) = fetch_bootloaders(&config, cookbook, live)?;
if let Some(write_bootloader) = write_bootloader {
if let Some(write_bootloader) = &config.general.write_bootloader {
std::fs::write(write_bootloader, &bootloader_efi)?;
}
let disk_option = DiskOption {
bootloader_bios: &bootloader_bios,
bootloader_efi: &bootloader_efi,
password_opt: None,
password_opt: password_opt,
efi_partition_size: config.general.efi_partition_size,
skip_partitions: config.general.skip_partitions.unwrap_or(false),
};
with_whole_disk(output, &disk_option, move |fs| {
with_redoxfs_mount(fs, move |mount_path| {
install_dir(config, mount_path, cookbook)
})
if config.general.no_mount.unwrap_or(false) {
with_redoxfs_ar(fs, move |mount_path| {
install_dir(config, mount_path, cookbook)
})
} else {
with_redoxfs_mount(fs, move |mount_path| {
install_dir(config, mount_path, cookbook)
})
}
})
}
}
pub fn install(
config: Config,
output: impl AsRef<Path>,
cookbook: Option<&str>,
live: bool,
write_bootloader: Option<&str>,
) -> Result<()> {
install_inner(config, output.as_ref(), cookbook, live, write_bootloader)
/// Install RedoxFS into a new disk file, or a sysroot directory.
/// This function assumes all interactive prompts resolved by the caller,
/// so "prompt" option is ignored from this function onward.
pub fn install(config: Config, output: impl AsRef<Path>) -> Result<()> {
install_inner(config, output.as_ref())
}