Refresh Red Bear runtime services

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-04-15 12:57:45 +01:00
parent d9faecc4ba
commit 01ce7a649b
6 changed files with 104 additions and 28 deletions
+1
View File
@@ -5,4 +5,5 @@ path = "source"
template = "cargo"
[package.files]
"/usr/bin/evdevd" = "evdevd"
"/usr/lib/drivers/evdevd" = "evdevd"
@@ -246,8 +246,8 @@ const INTEGRATIONS: &[IntegrationCheck] = &[
name: "iommu",
category: "System",
description: "IOMMU DMA-remapping daemon",
artifact_path: Some("/usr/lib/drivers/iommu"),
control_path: Some("/scheme"),
artifact_path: Some("/usr/bin/iommu"),
control_path: Some("/scheme/iommu"),
test_hint: "redbear-phase-iommu-check",
note: "Functional when the iommu scheme is registered in /scheme.",
functional_probe: Some(probe_iommu_scheme),
@@ -597,7 +597,7 @@ fn inspect_integration<'a>(
}
fn derive_state(artifact_present: Option<bool>, control_present: Option<bool>) -> ProbeState {
if control_present == Some(true) {
if control_present == Some(true) && artifact_present != Some(false) {
ProbeState::Active
} else if artifact_present == Some(true) {
ProbeState::Present
@@ -6,3 +6,7 @@ edition = "2024"
[[bin]]
name = "netctl"
path = "src/main.rs"
[[bin]]
name = "redbear-netctl"
path = "src/main.rs"
@@ -3,7 +3,23 @@ use std::fs;
use std::path::PathBuf;
use std::process::{self, Command};
const USAGE: &str = "Usage: netctl [--boot|list|status [profile]|start <profile>|stop <profile>|enable <profile>|disable [profile]|is-enabled [profile]]";
fn program_name() -> String {
env::args()
.next()
.and_then(|path| {
PathBuf::from(path)
.file_name()
.map(|name| name.to_string_lossy().into_owned())
})
.unwrap_or_else(|| "netctl".to_string())
}
fn usage() -> String {
format!(
"Usage: {} [--boot|list|status [profile]|start <profile>|stop <profile>|enable <profile>|disable [profile]|is-enabled [profile]]",
program_name()
)
}
#[derive(Clone, Debug)]
enum ProfileIpMode {
@@ -25,7 +41,7 @@ struct Profile {
fn main() {
if let Err(err) = run() {
eprintln!("netctl: {err}");
eprintln!("{}: {err}", program_name());
process::exit(1);
}
}
@@ -33,7 +49,7 @@ fn main() {
fn run() -> Result<(), String> {
let mut args = env::args().skip(1);
let Some(command) = args.next() else {
return Err(USAGE.into());
return Err(usage());
};
match command.as_str() {
@@ -46,15 +62,15 @@ fn run() -> Result<(), String> {
"disable" => disable_profile(args.next().as_deref()),
"is-enabled" => is_enabled(args.next().as_deref()),
"help" | "--help" | "-h" => {
println!("{USAGE}");
println!("{}", usage());
Ok(())
}
_ => Err(USAGE.into()),
_ => Err(usage()),
}
}
fn required_profile(profile: Option<String>) -> Result<String, String> {
profile.ok_or_else(|| USAGE.to_string())
profile.ok_or_else(usage)
}
fn run_boot_profile() -> Result<(), String> {
@@ -5,5 +5,6 @@ path = "source"
template = "cargo"
[package.files]
"/usr/bin/udev-shim" = "udev-shim"
"/usr/bin/udev" = "udev-shim"
"/usr/lib/drivers/udev" = "udev-shim"
@@ -1,4 +1,6 @@
use std::collections::BTreeMap;
use std::fs::File;
use std::io::Read;
use redox_scheme::scheme::SchemeSync;
use redox_scheme::{CallerCtx, OpenResult};
@@ -12,14 +14,13 @@ use crate::device_db::{
const SCHEME_ROOT_ID: usize = 1;
#[derive(Clone)]
enum HandleKind {
Root,
Devices,
Device(usize),
Dev,
DevInputDir,
DevInput(usize),
DevInput(usize, File),
DevInputMice,
DevDriDir,
DevDri(usize),
@@ -32,6 +33,32 @@ enum HandleKind {
Uevent,
}
impl Clone for HandleKind {
fn clone(&self) -> Self {
match self {
Self::Root => Self::Root,
Self::Devices => Self::Devices,
Self::Device(idx) => Self::Device(*idx),
Self::Dev => Self::Dev,
Self::DevInputDir => Self::DevInputDir,
Self::DevInput(idx, file) => Self::DevInput(
*idx,
file.try_clone().expect("udev-shim: clone dev input fd"),
),
Self::DevInputMice => Self::DevInputMice,
Self::DevDriDir => Self::DevDriDir,
Self::DevDri(idx) => Self::DevDri(*idx),
Self::DevLinks => Self::DevLinks,
Self::LinksInputDir => Self::LinksInputDir,
Self::LinksInputByPathDir => Self::LinksInputByPathDir,
Self::LinksDriDir => Self::LinksDriDir,
Self::LinksDriByPathDir => Self::LinksDriByPathDir,
Self::Link(idx) => Self::Link(*idx),
Self::Uevent => Self::Uevent,
}
}
}
pub struct UdevScheme {
next_id: usize,
handles: BTreeMap<usize, HandleKind>,
@@ -79,7 +106,7 @@ impl UdevScheme {
self.devices.push(classify_pci_device(bus, dev, func));
}
if path_exists("/scheme/input") {
if scheme_registered("input") {
self.devices.push(DeviceInfo::new_platform_input(
"Redox Keyboard Input",
"/devices/platform/keyboard0",
@@ -89,7 +116,7 @@ impl UdevScheme {
));
}
if path_exists("/scheme/pointer") || path_exists("/scheme/mouse") {
if scheme_registered("pointer") || scheme_registered("mouse") {
self.devices.push(DeviceInfo::new_platform_input(
"Redox Mouse Input",
"/devices/platform/mouse0",
@@ -275,7 +302,7 @@ impl UdevScheme {
}
Ok(self.directory_listing(entries))
}
HandleKind::DevInput(idx) => {
HandleKind::DevInput(idx, _) => {
let dev = self.devices.get(*idx).ok_or_else(|| Error::new(ENOENT))?;
if dev.scheme_target.is_empty() {
return Err(Error::new(ENOENT));
@@ -391,7 +418,13 @@ impl UdevScheme {
let idx = self
.find_device_by_devnode(&devnode)
.ok_or_else(|| Error::new(ENOENT))?;
Ok(HandleKind::DevInput(idx))
let dev = self.devices.get(idx).ok_or_else(|| Error::new(ENOENT))?;
if dev.scheme_target.is_empty() {
return Err(Error::new(ENOENT));
}
let file = File::open(format!("/scheme/{}", dev.scheme_target))
.map_err(|_| Error::new(ENOENT))?;
Ok(HandleKind::DevInput(idx, file))
} else if let Some(rest) = cleaned.strip_prefix("dev/dri/") {
let devnode = format!("/dev/dri/{rest}");
let idx = self
@@ -434,7 +467,7 @@ impl UdevScheme {
}
HandleKind::Dev => Ok("/scheme/udev/dev".to_string()),
HandleKind::DevInputDir => Ok("/scheme/udev/dev/input".to_string()),
HandleKind::DevInput(idx) => self
HandleKind::DevInput(idx, _) => self
.devices
.get(*idx)
.filter(|dev| !dev.devnode.is_empty())
@@ -503,18 +536,23 @@ impl SchemeSync for UdevScheme {
_ctx: &CallerCtx,
) -> Result<usize> {
let kind = self.kind_for_id(id)?;
let content = self.content_for_handle(&kind)?;
let bytes = content.as_bytes();
match kind {
HandleKind::DevInput(_, mut file) => file.read(buf).map_err(|_| Error::new(ENOENT)),
_ => {
let content = self.content_for_handle(&kind)?;
let bytes = content.as_bytes();
if offset >= bytes.len() as u64 {
return Ok(0);
if offset >= bytes.len() as u64 {
return Ok(0);
}
let start = offset as usize;
let remaining = &bytes[start..];
let to_copy = remaining.len().min(buf.len());
buf[..to_copy].copy_from_slice(&remaining[..to_copy]);
Ok(to_copy)
}
}
let start = offset as usize;
let remaining = &bytes[start..];
let to_copy = remaining.len().min(buf.len());
buf[..to_copy].copy_from_slice(&remaining[..to_copy]);
Ok(to_copy)
}
fn write(
@@ -540,7 +578,10 @@ impl SchemeSync for UdevScheme {
fn fstat(&mut self, id: usize, stat: &mut syscall::Stat, _ctx: &CallerCtx) -> Result<()> {
let kind = self.kind_for_id(id)?;
let size = self.content_for_handle(&kind)?.len() as u64;
let size = match kind {
HandleKind::DevInput(_, _) => 0,
_ => self.content_for_handle(&kind)?.len() as u64,
};
stat.st_mode = if Self::is_directory(&kind) {
MODE_DIR | 0o555
@@ -567,7 +608,10 @@ impl SchemeSync for UdevScheme {
fn fsize(&mut self, id: usize, _ctx: &CallerCtx) -> Result<u64> {
let kind = self.kind_for_id(id)?;
Ok(self.content_for_handle(&kind)?.len() as u64)
Ok(match kind {
HandleKind::DevInput(_, _) => 0,
_ => self.content_for_handle(&kind)?.len() as u64,
})
}
fn ftruncate(&mut self, id: usize, _len: u64, _ctx: &CallerCtx) -> Result<()> {
@@ -591,6 +635,16 @@ fn path_exists(path: &str) -> bool {
std::fs::metadata(path).is_ok()
}
fn scheme_registered(name: &str) -> bool {
std::fs::read_dir("/scheme")
.ok()
.into_iter()
.flatten()
.filter_map(Result::ok)
.filter_map(|entry| entry.file_name().into_string().ok())
.any(|entry| entry == name)
}
fn parse_pci_slot(name: &str) -> Option<(u8, u8, u8)> {
let mut parts = name.split('.');
let bus = parts.next()?.parse::<u8>().ok()?;