base: apply Red Bear patches on latest upstream/main

251 files: init, acpid, ipcd, netcfg, ihdgd, virtio-gpud, scheme-utils,
inputd, block driver, ptyd, ramfs, randd, initfs bootstrap, path deps,
version +rb0.3.1, author attribution
This commit is contained in:
Red Bear OS
2026-07-11 11:39:24 +03:00
parent 1b17b3fc24
commit bd595851e2
251 changed files with 24641 additions and 5993 deletions
+35 -14
View File
@@ -29,7 +29,6 @@ struct InitConfig {
log_debug: bool,
skip_cmd: Vec<String>,
envs: BTreeMap<String, OsString>,
cwd: OsString,
}
impl InitConfig {
@@ -45,18 +44,11 @@ impl InitConfig {
log_debug,
skip_cmd,
envs: BTreeMap::from([("RUST_BACKTRACE".to_owned(), "1".into())]),
cwd: "/scheme/initfs".into(),
}
}
}
fn switch_root(
unit_store: &mut UnitStore,
config: &mut InitConfig,
prefix: &Path,
etcdir: &Path,
cwd: &Path,
) {
fn switch_root(unit_store: &mut UnitStore, config: &mut InitConfig, prefix: &Path, etcdir: &Path) {
eprintln!(
"init: switchroot to {} {}",
prefix.display(),
@@ -70,7 +62,6 @@ fn switch_root(
"LD_LIBRARY_PATH".to_owned(),
prefix.join("lib").into_os_string(),
);
config.cwd = cwd.to_path_buf().into_os_string();
unit_store.config_dirs = vec![prefix.join("lib").join("init.d"), etcdir.join("init.d")];
@@ -122,16 +113,20 @@ fn switch_root(
}
fn main() {
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
use std::io::Write;
let _ = writeln!(f, "INIT: main() entered");
}
let mut init_config = InitConfig::new();
let mut unit_store = UnitStore::new();
let mut scheduler = Scheduler::new();
eprintln!("INIT: about to switch_root (initfs)");
switch_root(
&mut unit_store,
&mut init_config,
Path::new("/scheme/initfs"),
Path::new("/scheme/initfs/etc"),
Path::new("/scheme/initfs"),
);
// Start logd first such that we can pass /scheme/log as stdio to all other services
@@ -155,7 +150,6 @@ fn main() {
&mut init_config,
Path::new("/usr"),
Path::new("/etc"),
Path::new("/"),
);
{
// FIXME introduce multi-user.target unit and replace the config dir iteration
@@ -177,16 +171,43 @@ fn main() {
}
};
for entry in entries {
let file_name = entry.file_name().unwrap();
if file_name.to_str().map_or(false, |name| name.starts_with('.')) {
continue;
}
scheduler.schedule_start_and_report_errors(
&mut unit_store,
UnitId(entry.file_name().unwrap().to_str().unwrap().to_owned()),
UnitId(file_name.to_str().unwrap().to_owned()),
);
}
};
eprintln!("INIT: starting /usr scheduler step");
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
use std::io::Write;
let _ = writeln!(f, "BEFORE_STEP");
}
scheduler.step(&mut unit_store, &mut init_config);
eprintln!("INIT: waitpid loop");
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
use std::io::Write;
let _ = writeln!(f, "AFTER_STEP");
}
libredox::call::setrens(0, 0).expect("init: failed to enter null namespace");
// Enter a null namespace containing only memory and pipe schemes. This
// limits what daemons can access if they crash or misbehave. For the
// initial bootstrap init (started directly by the kernel), there is no
// prior ns_fd, so the kernel falls back to the root scheme list. If
// setrens fails (e.g. ns_fd unavailable), we log a warning and continue
// — the init process can still function with the full scheme set.
if let Err(e) = libredox::call::setrens(0, 0) {
eprintln!("INIT: warning, could not enter null namespace: {e}");
eprintln!("INIT: continuing with full scheme set");
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
use std::io::Write;
let _ = writeln!(f, "INIT: setrens warning: {e}");
}
}
loop {
let mut status = 0;
+25 -3
View File
@@ -1,4 +1,5 @@
use std::collections::VecDeque;
use std::collections::{BTreeMap, VecDeque};
use std::io::Write;
use crate::InitConfig;
use crate::unit::{Unit, UnitId, UnitKind, UnitStore};
@@ -55,8 +56,12 @@ impl Scheduler {
}
pub fn step(&mut self, unit_store: &mut UnitStore, init_config: &mut InitConfig) {
let mut defer_count: BTreeMap<String, usize> = BTreeMap::new();
'a: loop {
let Some(job) = self.pending.pop_front() else {
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
let _ = writeln!(f, "STEP_DONE");
}
return;
};
@@ -64,16 +69,33 @@ impl Scheduler {
JobKind::Start => {
let unit = unit_store.unit_mut(&job.unit);
let mut blocked = false;
for dep in &unit.info.requires_weak {
for pending_job in &self.pending {
if &pending_job.unit == dep {
self.pending.push_back(job);
continue 'a;
blocked = true;
break;
}
}
if blocked { break; }
}
if blocked {
let cnt = defer_count.entry(job.unit.0.clone()).or_insert(0);
*cnt += 1;
if *cnt <= 3 {
self.pending.push_back(job);
continue 'a;
}
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
let _ = writeln!(f, "FORCE {}", job.unit.0);
}
}
run(unit, init_config);
if let Ok(mut f) = std::fs::OpenOptions::new().write(true).open("/scheme/debug/no-preserve") {
let _ = writeln!(f, "RAN {}", unit.id.0);
}
}
}
}
-1
View File
@@ -97,7 +97,6 @@ impl Command {
command.args(process.args.iter().map(|arg| subst_env(arg)));
command.env_clear();
command.envs(&config.envs).envs(&process.envs);
command.current_dir(&config.cwd);
let mut child = match command.spawn() {
Ok(child) => child,
+9 -9
View File
@@ -1,7 +1,7 @@
use std::collections::{BTreeMap, BTreeSet};
use std::ffi::OsString;
use std::io::Read;
use std::os::fd::{AsRawFd, RawFd};
use std::os::fd::{AsRawFd, OwnedFd};
use std::os::unix::process::CommandExt;
use std::process::Command;
use std::{env, io};
@@ -47,7 +47,7 @@ impl Service {
command.envs(base_envs).envs(&self.envs);
let (mut read_pipe, write_pipe) = io::pipe().unwrap();
unsafe { pass_fd(&mut command, "INIT_NOTIFY", write_pipe.as_raw_fd()) };
unsafe { pass_fd(&mut command, "INIT_NOTIFY", write_pipe.into()) };
let mut child = match command.spawn() {
Ok(child) => child,
@@ -56,7 +56,6 @@ impl Service {
return;
}
};
drop(write_pipe);
match &self.type_ {
ServiceType::Notify => match read_pipe.read_exact(&mut [0]) {
@@ -70,15 +69,16 @@ impl Service {
},
ServiceType::Scheme(scheme) => {
let mut new_fd = usize::MAX;
loop {
match libredox::call::call_ro(
match syscall::call_ro(
read_pipe.as_raw_fd() as usize,
unsafe { plain::as_mut_bytes(&mut new_fd) },
syscall::CallFlags::FD | syscall::CallFlags::FD_UPPER,
&[],
) {
Err(err) if err.is_interrupt() => continue,
Err(syscall::Error {
errno: syscall::EINTR,
}) => continue,
Ok(0) => {
eprintln!("init: {command:?} exited without notifying readiness");
return;
@@ -117,12 +117,12 @@ impl Service {
}
}
unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: RawFd) {
cmd.env(env, format!("{}", fd));
unsafe fn pass_fd(cmd: &mut Command, env: &str, fd: OwnedFd) {
cmd.env(env, format!("{}", fd.as_raw_fd()));
unsafe {
cmd.pre_exec(move || {
// Pass notify pipe to child
if libc::fcntl(fd, libc::F_SETFD, 0) == -1 {
if libc::fcntl(fd.as_raw_fd(), libc::F_SETFD, 0) == -1 {
Err(io::Error::last_os_error())
} else {
Ok(())