From 0c7353bfad3d4591d3250fb38038bc564df837a2 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Mon, 25 May 2026 11:11:24 +0200 Subject: [PATCH 1/2] Fix and port more apps for uutils-procps --- recipes/wip/rs/uutils-procps/recipe.toml | 29 +++++++++++++++---- recipes/wip/rs/uutils-procps/redox.patch | 37 ++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 recipes/wip/rs/uutils-procps/redox.patch diff --git a/recipes/wip/rs/uutils-procps/recipe.toml b/recipes/wip/rs/uutils-procps/recipe.toml index 9fc042cc..caf04ab1 100644 --- a/recipes/wip/rs/uutils-procps/recipe.toml +++ b/recipes/wip/rs/uutils-procps/recipe.toml @@ -1,22 +1,41 @@ -#TODO: common libc functions such as getsid -#TODO: only watch is working +#TODO: common libc functions such as getsid and utmpx in rustix [source] git = "https://github.com/uutils/procps" +rev = "ee98c0a78fe2abe72589f80eb05b455fa228e757" +patches = [ "redox.patch" ] shallow_clone = true [build] template = "custom" script = """ DYNAMIC_INIT -# TODO: more features support? -CARGO_PROFILE_RELEASE_LTO=thin cookbook_cargo --no-default-features --features pmap,slabtop,sysctl,tload,vmstat,watch BINS=( + #free + hugetop + pgrep + pidof + pidwait + pkill + pmap + ps + pwdx + skill + snice + sysctl + tload + #top + vmstat + #w watch ) +(IFS=,; CARGO_PROFILE_RELEASE_LTO=thin cookbook_cargo --no-default-features --features "${BINS[*]}") + for bin in "${BINS[@]}" do ln -sv procps "${COOKBOOK_STAGE}/usr/bin/$bin" done -""" +# conflict with coreutils +rm "${COOKBOOK_STAGE}/usr/bin/ps" +""" diff --git a/recipes/wip/rs/uutils-procps/redox.patch b/recipes/wip/rs/uutils-procps/redox.patch new file mode 100644 index 00000000..d7435bde --- /dev/null +++ b/recipes/wip/rs/uutils-procps/redox.patch @@ -0,0 +1,37 @@ +diff --git a/src/uu/pgrep/src/process_matcher.rs b/src/uu/pgrep/src/process_matcher.rs +index c991092..33adcff 100644 +--- a/src/uu/pgrep/src/process_matcher.rs ++++ b/src/uu/pgrep/src/process_matcher.rs +@@ -452,14 +452,14 @@ pub fn getpgrp() -> u64 { + + /// Dummy implementation for unsupported platforms. + pub fn getsid(_pid: u32) -> u64 { +- #[cfg(unix)] ++ #[cfg(all(unix, not(target_os = "redox")))] + { + rustix::process::getsid(None) + .ok() + .map(|pid: rustix::process::Pid| pid.as_raw_nonzero().get() as u64) + .unwrap_or(0) + } +- #[cfg(not(unix))] ++ #[cfg(not(all(unix, not(target_os = "redox"))))] + { + 0 + } +diff --git a/src/uu/ps/src/process_selection.rs b/src/uu/ps/src/process_selection.rs +index c2a0a5a..65c33a2 100644 +--- a/src/uu/ps/src/process_selection.rs ++++ b/src/uu/ps/src/process_selection.rs +@@ -20,6 +20,11 @@ fn getsid(pid: i32) -> Option { + } + } + ++#[cfg(target_os = "redox")] ++fn getsid(_pid: i32) -> Option { ++ None ++} ++ + // TODO: Temporary add to this file, this function will add to uucore. + #[cfg(target_family = "windows")] + fn getsid(_pid: i32) -> Option { From 7b2e53d56730a4aeded6456b9fc8e3ecaefef569 Mon Sep 17 00:00:00 2001 From: Wildan M Date: Sat, 23 May 2026 15:15:01 +0700 Subject: [PATCH 2/2] Patch procps logic to use sys/context --- recipes/wip/rs/uutils-procps/redox.patch | 293 +++++++++++++++++++++++ 1 file changed, 293 insertions(+) diff --git a/recipes/wip/rs/uutils-procps/redox.patch b/recipes/wip/rs/uutils-procps/redox.patch index d7435bde..bbae9ec0 100644 --- a/recipes/wip/rs/uutils-procps/redox.patch +++ b/recipes/wip/rs/uutils-procps/redox.patch @@ -1,3 +1,272 @@ +diff --git a/src/uu/pgrep/src/process.rs b/src/uu/pgrep/src/process.rs +index 6dce047..a1721ac 100644 +--- a/src/uu/pgrep/src/process.rs ++++ b/src/uu/pgrep/src/process.rs +@@ -422,6 +422,7 @@ impl Namespace { + } + + /// Process ID and its information ++#[cfg(target_os = "linux")] + #[derive(Debug, Clone, Default)] + pub struct ProcessInformation { + pub pid: usize, +@@ -440,6 +441,21 @@ pub struct ProcessInformation { + thread_ids: OnceLock>, + } + ++#[cfg(target_os = "redox")] ++#[derive(Debug, Clone, Default)] ++pub struct ProcessInformation { ++ pub pid: usize, ++ pub cmdline: String, ++ pub name: String, ++ pub euid: u32, ++ pub egid: u32, ++ pub time_str: String, ++ pub run_state_str: String, ++ pub inner_status: String, ++ pub inner_stat: String, ++} ++ ++#[cfg(target_os = "linux")] + impl ProcessInformation { + /// Try new with pid path such as `/proc/self` + /// +@@ -729,6 +745,166 @@ impl ProcessInformation { + Namespace::from_pid(self.pid) + } + } ++ ++#[cfg(target_os = "redox")] ++impl ProcessInformation { ++ pub fn try_new(line: &str) -> Result { ++ let parts: Vec<&str> = line.split_whitespace().collect(); ++ // PID EUID EGID STAT CPU AFFINITY TIME PRIVATE PRIVATE_UNIT SHARED SHARED_UNIT NAME ++ if parts.len() < 12 { ++ return Err(io::Error::new( ++ io::ErrorKind::InvalidData, ++ "parts incomplete", ++ )); ++ } ++ ++ let pid = parts[0] ++ .parse::() ++ .map_err(|_| io::ErrorKind::InvalidData)?; ++ let euid = parts[1] ++ .parse::() ++ .map_err(|_| io::ErrorKind::InvalidData)?; ++ let egid = parts[2] ++ .parse::() ++ .map_err(|_| io::ErrorKind::InvalidData)?; ++ let run_state_str = parts[3].to_string(); ++ let time_str = parts[6].to_string(); ++ ++ let name = parts.last().unwrap_or(&"").to_string(); ++ let cmdline = name.clone(); ++ ++ Ok(Self { ++ pid, ++ cmdline, ++ name, ++ euid, ++ egid, ++ run_state_str, ++ time_str, ++ inner_status: String::new(), ++ inner_stat: String::new(), ++ }) ++ } ++ ++ pub fn from_pid(pid: usize) -> Result { ++ let content = fs::read_to_string("/scheme/sys/context")?; ++ for line in content.lines() { ++ if let Ok(proc_info) = Self::try_new(line) { ++ if proc_info.pid == pid { ++ return Ok(proc_info); ++ } ++ } ++ } ++ Err(io::Error::new(io::ErrorKind::NotFound, "no process found")) ++ } ++ ++ pub fn current_process_info() -> Result { ++ let pid = rustix::process::getpid(); ++ Self::from_pid(pid.as_raw_pid() as usize) ++ } ++ ++ pub fn proc_status(&self) -> &str { ++ "" ++ } ++ pub fn proc_stat(&self) -> &str { ++ "" ++ } ++ ++ pub fn name(&mut self) -> Result { ++ Ok(self.name.clone()) ++ } ++ ++ pub fn start_time(&mut self) -> Result { ++ Ok(0) ++ } ++ ++ pub fn ppid(&mut self) -> Result { ++ Ok(0) ++ } ++ pub fn pgid(&mut self) -> Result { ++ Ok(0) ++ } ++ pub fn sid(&mut self) -> Result { ++ Ok(0) ++ } ++ ++ pub fn uid(&mut self) -> Result { ++ Ok(self.euid) ++ } ++ pub fn euid(&mut self) -> Result { ++ Ok(self.euid) ++ } ++ pub fn gid(&mut self) -> Result { ++ Ok(self.egid) ++ } ++ pub fn egid(&mut self) -> Result { ++ Ok(self.egid) ++ } ++ pub fn suid(&mut self) -> Result { ++ Ok(self.euid) ++ } ++ pub fn sgid(&mut self) -> Result { ++ Ok(self.egid) ++ } ++ ++ pub fn signals_caught_mask(&mut self) -> Result { ++ Ok(0) ++ } ++ pub fn signals_pending_mask(&mut self) -> Result { ++ Ok(0) ++ } ++ pub fn signals_blocked_mask(&mut self) -> Result { ++ Ok(0) ++ } ++ pub fn signals_ignored_mask(&mut self) -> Result { ++ Ok(0) ++ } ++ ++ pub fn root(&mut self) -> Result { ++ Ok(PathBuf::from("/")) ++ } ++ ++ pub fn cgroups(&mut self) -> Result, io::Error> { ++ Ok(vec![]) ++ } ++ pub fn cgroup_v2_path(&mut self) -> Result { ++ Err(io::Error::new(io::ErrorKind::Unsupported, "no cgroups")) ++ } ++ ++ pub fn run_state(&mut self) -> Result { ++ match self.run_state_str.as_str() { ++ "RR" | "UR" => RunState::try_from("R"), ++ "UB" => RunState::try_from("S"), ++ _ => RunState::try_from("S"), ++ } ++ } ++ ++ pub fn tty(&mut self) -> Teletype { ++ Teletype::Unknown ++ } ++ ++ pub fn thread_ids(&mut self) -> &[usize] { ++ &[] ++ } ++ ++ pub fn env_vars(&self) -> Result, io::Error> { ++ Ok(HashMap::new()) ++ } ++ ++ pub fn namespaces(&self) -> Result { ++ Err(io::Error::new(io::ErrorKind::Unsupported, "no namespaces")) ++ } ++} ++#[cfg(target_os = "redox")] ++impl TryFrom<&str> for ProcessInformation { ++ type Error = io::Error; ++ ++ fn try_from(value: &str) -> Result { ++ Self::try_new(value) ++ } ++} ++ ++#[cfg(target_os = "linux")] + impl TryFrom for ProcessInformation { + type Error = io::Error; + +@@ -751,6 +927,7 @@ impl Hash for ProcessInformation { + /// Parsing `/proc/self/stat` file. + /// + /// TODO: If possible, test and use regex to replace this algorithm. ++#[cfg(target_os = "linux")] + fn stat_split(stat: &str) -> Vec { + let stat = String::from(stat); + +@@ -767,6 +944,7 @@ fn stat_split(stat: &str) -> Vec { + } + } + ++#[cfg(target_os = "linux")] + /// Iterating pid in current system + pub fn walk_process() -> impl Iterator { + WalkDir::new("/proc/") +@@ -778,10 +956,12 @@ pub fn walk_process() -> impl Iterator { + .flat_map(ProcessInformation::try_from) + } + ++#[cfg(target_os = "linux")] + static THREAD_REGEX: LazyLock = LazyLock::new(|| { + Regex::new(r"^/proc/[0-9]+$|^/proc/[0-9]+/task$|^/proc/[0-9]+/task/[0-9]+$").unwrap() + }); + ++#[cfg(target_os = "linux")] + pub fn walk_threads() -> impl Iterator { + WalkDir::new("/proc/") + .min_depth(1) +@@ -794,6 +974,38 @@ pub fn walk_threads() -> impl Iterator { + .flat_map(ProcessInformation::try_from) + } + ++#[cfg(target_os = "redox")] ++pub fn walk_process() -> impl Iterator { ++ use std::collections::HashSet; ++ ++ let content = fs::read_to_string("/scheme/sys/context").unwrap(); ++ ++ let mut processes = Vec::new(); ++ let mut seen_pids = HashSet::new(); ++ ++ for line in content.lines() { ++ if let Ok(proc_info) = ProcessInformation::try_new(line) { ++ if seen_pids.insert(proc_info.pid) { ++ processes.push(proc_info); ++ } ++ } ++ } ++ processes.into_iter() ++} ++ ++#[cfg(target_os = "redox")] ++pub fn walk_threads() -> impl Iterator { ++ let content = fs::read_to_string("/scheme/sys/context").unwrap(); ++ ++ let mut threads = Vec::new(); ++ for line in content.lines() { ++ if let Ok(proc_info) = ProcessInformation::try_new(line) { ++ threads.push(proc_info); ++ } ++ } ++ threads.into_iter() ++} ++ + #[cfg(test)] + mod tests { + use super::*; diff --git a/src/uu/pgrep/src/process_matcher.rs b/src/uu/pgrep/src/process_matcher.rs index c991092..33adcff 100644 --- a/src/uu/pgrep/src/process_matcher.rs @@ -19,6 +288,30 @@ index c991092..33adcff 100644 { 0 } +diff --git a/src/uu/ps/src/picker.rs b/src/uu/ps/src/picker.rs +index be0a1c4..496bf2d 100644 +--- a/src/uu/ps/src/picker.rs ++++ b/src/uu/ps/src/picker.rs +@@ -148,13 +148,17 @@ fn time(proc_info: RefCell) -> String { + // https://docs.kernel.org/filesystems/proc.html#id10 + // Index of 13 14 + ++ #[cfg(target_os = "linux")] + let cumulative_cpu_time = { + let utime = proc_info.borrow_mut().stat()[13].parse::().unwrap(); + let stime = proc_info.borrow_mut().stat()[14].parse::().unwrap(); +- (utime + stime) / 100 ++ format_time((utime + stime) / 100) + }; + +- format_time(cumulative_cpu_time) ++ #[cfg(target_os = "redox")] ++ let cumulative_cpu_time = { proc_info.borrow_mut().time_str.clone() }; ++ ++ cumulative_cpu_time + } + + fn format_time(seconds: i64) -> String { diff --git a/src/uu/ps/src/process_selection.rs b/src/uu/ps/src/process_selection.rs index c2a0a5a..65c33a2 100644 --- a/src/uu/ps/src/process_selection.rs