init: Introduce switchroot command

This sets PATH, LD_LIBRARY_PATH and runs init scripts for the new root.
In the future this could replace the entire set of services that should
run, restarting any services for which a newer executable is available
in the new root and stopping any services which don't exist in the new
root. This behavior could also be useful for soft-reboots in the future
to handle updates without rebooting the entire system.
This commit is contained in:
bjorn3
2026-02-19 20:18:07 +01:00
parent a5168828ad
commit 0227c0677c
5 changed files with 45 additions and 44 deletions
+1
View File
@@ -100,6 +100,7 @@ pub fn main() -> ! {
.filter(|var| !var.starts_with(b"INITFS_"))
.collect::<Vec<_>>()
};
envs.push(b"RUST_BACKTRACE=1");
//envs.push(b"LD_DEBUG=all");
envs.push(b"LD_LIBRARY_PATH=/scheme/initfs/lib");
+1 -5
View File
@@ -1,8 +1,4 @@
# Various daemons that relibc needs to function as well as a bunch of env vars
# that should be set for every program.
export PATH /scheme/initfs/bin
export LD_LIBRARY_PATH /scheme/initfs/lib
export RUST_BACKTRACE 1
# Various daemons that relibc needs to function.
rtcd
scheme null nulld
scheme zero zerod
+1 -3
View File
@@ -1,4 +1,2 @@
cd /
export PATH /usr/bin
export LD_LIBRARY_PATH /usr/lib
run.d /usr/lib/init.d /etc/init.d
switchroot /usr /etc
+30 -26
View File
@@ -42,6 +42,29 @@ impl InitConfig {
}
}
fn switch_root(prefix: &Path, etcdir: &Path, config: &InitConfig) {
unsafe {
env::set_var("PATH", prefix.join("bin"));
env::set_var("LD_LIBRARY_PATH", prefix.join("lib"));
}
let entries = match config::config_for_dirs(&[
prefix.join("lib").join("init.d"),
etcdir.join("init.d"),
]) {
Ok(list) => list,
Err(err) => {
eprintln!("init: failed to switchroot: '{prefix:?}', '{etcdir:?}': {err}");
return;
}
};
for entry_path in entries {
if let Err(err) = run(&entry_path, config) {
eprintln!("init: failed to run '{}': {}", entry_path.display(), err);
}
}
}
fn run(file: &Path, config: &InitConfig) -> Result<()> {
let (script, errors) = script::Script::from_file(file)?;
@@ -69,20 +92,8 @@ fn run_command(cmd: Command, config: &InitConfig) {
}
Command::Echo(text) => println!("{text}"),
Command::Export(var, value) => unsafe { env::set_var(var, value) },
Command::RunD(dirs) => {
let entries = match config::config_for_dirs(&dirs) {
Ok(list) => list,
Err(err) => {
eprintln!("init: failed to run.d: '{dirs:?}': {err}");
return;
}
};
for entry_path in entries {
if let Err(err) = run(&entry_path, config) {
eprintln!("init: failed to run '{}': {}", entry_path.display(), err);
}
}
Command::SwitchRoot(prefix, etcdir) => {
switch_root(&prefix, &etcdir, config);
}
Command::Stdio(stdio) => {
if let Err(err) = switch_stdio(&stdio) {
@@ -166,18 +177,11 @@ fn run_command(cmd: Command, config: &InitConfig) {
fn main() {
let init_config = InitConfig::new();
let entries = match config::config_for_initfs("init") {
Ok(entries) => entries,
Err(err) => {
eprintln!("init: failed to find config files: {}", err);
return;
}
};
for entry_path in entries {
if let Err(err) = run(&entry_path, &init_config) {
eprintln!("init: failed to run '{}': {}", entry_path.display(), err);
}
}
switch_root(
Path::new("/scheme/initfs"),
Path::new("/scheme/initfs/etc"),
&init_config,
);
libredox::call::setrens(0, 0).expect("init: failed to enter null namespace");
+12 -10
View File
@@ -48,7 +48,7 @@ pub enum Command {
// Misc
Echo(String),
RunD(Vec<PathBuf>),
SwitchRoot(PathBuf, PathBuf),
Nothing,
}
@@ -80,15 +80,17 @@ impl Command {
}
Ok(Command::Export(var, value))
}
"run.d" => {
let args = args.map(|arg| PathBuf::from(arg)).collect::<Vec<_>>();
if args.is_empty() {
return Err(
"init: failed to run.d: no argument or all dirs are non-existent"
.to_owned(),
);
}
Ok(Command::RunD(args))
"switchroot" => {
let Some(prefix) = args.next() else {
return Err("init: failed to switchroot: no argument".to_owned());
};
let Some(etcdir) = args.next() else {
return Err("init: failed to switchroot: missing etcdir".to_owned());
};
Ok(Command::SwitchRoot(
PathBuf::from(prefix),
PathBuf::from(etcdir),
))
}
"stdio" => {
let Some(stdio) = args.next() else {