From 16c174d82684a83f76167889305650370f9ce3ce Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Mon, 24 Feb 2025 12:00:45 +0200 Subject: [PATCH 1/3] uucore: Sync thread_ids() method from procps --- src/uucore/src/lib/features/proc_info.rs | 48 +++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/proc_info.rs b/src/uucore/src/lib/features/proc_info.rs index f40847c1d..32eb07461 100644 --- a/src/uucore/src/lib/features/proc_info.rs +++ b/src/uucore/src/lib/features/proc_info.rs @@ -129,6 +129,8 @@ pub struct ProcessInformation { cached_stat: Option>>, cached_start_time: Option, + + cached_thread_ids: Option>>, } impl ProcessInformation { @@ -271,8 +273,33 @@ impl ProcessInformation { Teletype::Unknown } -} + pub fn thread_ids(&mut self) -> Rc> { + if let Some(c) = &self.cached_thread_ids { + return Rc::clone(c); + } + + let thread_ids_dir = format!("/proc/{}/task", self.pid); + let result = Rc::new( + WalkDir::new(thread_ids_dir) + .min_depth(1) + .max_depth(1) + .follow_links(false) + .into_iter() + .flatten() + .flat_map(|it| { + it.path() + .file_name() + .and_then(|it| it.to_str()) + .and_then(|it| it.parse::().ok()) + }) + .collect::>(), + ); + + self.cached_thread_ids = Some(Rc::clone(&result)); + Rc::clone(&result) + } +} impl TryFrom for ProcessInformation { type Error = io::Error; @@ -399,6 +426,25 @@ mod tests { ); } + #[test] + fn test_thread_ids() { + let main_tid = unsafe { uucore::libc::gettid() }; + std::thread::spawn(move || { + let mut pid_entry = ProcessInformation::try_new( + PathBuf::from_str(&format!("/proc/{}", current_pid())).unwrap(), + ) + .unwrap(); + let thread_ids = pid_entry.thread_ids(); + + assert!(thread_ids.contains(&(main_tid as usize))); + + let new_thread_tid = unsafe { uucore::libc::gettid() }; + assert!(thread_ids.contains(&(new_thread_tid as usize))); + }) + .join() + .unwrap(); + } + #[test] fn test_stat_split() { let case = "32 (idle_inject/3) S 2 0 0 0 -1 69238848 0 0 0 0 0 0 0 0 -51 0 1 0 34 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 0 0 0 17 3 50 1 0 0 0 0 0 0 0 0 0 0 0"; From 339a6d4c463df935b1f635f1fc3027d667134368 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Mon, 24 Feb 2025 12:01:23 +0200 Subject: [PATCH 2/3] uucore: Sync uid/gid methods from procps --- src/uucore/src/lib/features/proc_info.rs | 55 ++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/uucore/src/lib/features/proc_info.rs b/src/uucore/src/lib/features/proc_info.rs index 32eb07461..bbcaae91c 100644 --- a/src/uucore/src/lib/features/proc_info.rs +++ b/src/uucore/src/lib/features/proc_info.rs @@ -133,6 +133,12 @@ pub struct ProcessInformation { cached_thread_ids: Option>>, } +#[derive(Clone, Copy, Debug)] +enum UidGid { + Uid, + Gid, +} + impl ProcessInformation { /// Try new with pid path such as `/proc/self` /// @@ -239,6 +245,43 @@ impl ProcessInformation { Ok(time) } + pub fn ppid(&mut self) -> Result { + // the PPID is the fourth field in /proc//stat + // (https://www.kernel.org/doc/html/latest/filesystems/proc.html#id10) + self.stat() + .get(3) + .ok_or(io::ErrorKind::InvalidData)? + .parse::() + .map_err(|_| io::ErrorKind::InvalidData.into()) + } + + fn get_uid_or_gid_field(&mut self, field: UidGid, index: usize) -> Result { + self.status() + .get(&format!("{:?}", field)) + .ok_or(io::ErrorKind::InvalidData)? + .split_whitespace() + .nth(index) + .ok_or(io::ErrorKind::InvalidData)? + .parse::() + .map_err(|_| io::ErrorKind::InvalidData.into()) + } + + pub fn uid(&mut self) -> Result { + self.get_uid_or_gid_field(UidGid::Uid, 0) + } + + pub fn euid(&mut self) -> Result { + self.get_uid_or_gid_field(UidGid::Uid, 1) + } + + pub fn gid(&mut self) -> Result { + self.get_uid_or_gid_field(UidGid::Gid, 0) + } + + pub fn egid(&mut self) -> Result { + self.get_uid_or_gid_field(UidGid::Gid, 1) + } + /// Fetch run state from [ProcessInformation::cached_stat] /// /// - [The /proc Filesystem: Table 1-4](https://docs.kernel.org/filesystems/proc.html#id10) @@ -456,4 +499,16 @@ mod tests { let case = "47246 (kworker /10:1-events) I 2 0 0 0 -1 69238880 0 0 0 0 17 29 0 0 20 0 1 0 1396260 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 0 0 0 17 10 0 0 0 0 0 0 0 0 0 0 0 0 0"; assert!(stat_split(case)[1] == "kworker /10:1-events"); } + + #[test] + fn test_uid_gid() { + let mut pid_entry = ProcessInformation::try_new( + PathBuf::from_str(&format!("/proc/{}", current_pid())).unwrap(), + ) + .unwrap(); + assert_eq!(pid_entry.uid().unwrap(), uucore::process::getuid()); + assert_eq!(pid_entry.euid().unwrap(), uucore::process::geteuid()); + assert_eq!(pid_entry.gid().unwrap(), uucore::process::getgid()); + assert_eq!(pid_entry.egid().unwrap(), uucore::process::getegid()); + } } From 88b93a6865483218fb378e9d7cac569f89c392e4 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Mon, 24 Feb 2025 12:31:32 +0200 Subject: [PATCH 3/3] uucore: Extend proc_info spell checker list --- src/uucore/src/lib/features/proc_info.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/uucore/src/lib/features/proc_info.rs b/src/uucore/src/lib/features/proc_info.rs index bbcaae91c..c8bede26b 100644 --- a/src/uucore/src/lib/features/proc_info.rs +++ b/src/uucore/src/lib/features/proc_info.rs @@ -4,6 +4,7 @@ // file that was distributed with this source code. // spell-checker:ignore exitstatus cmdline kworker pgrep pwait snice procps +// spell-checker:ignore egid euid gettid ppid //! Set of functions to manage IDs //!