pgrep: remove libc in pgrep

Use rustix instead of libc and unsafe functions such as getpgrp, getsid, flock, gettid, getppid, getpgid, and getsid.
This commit is contained in:
yushuoqi
2026-02-09 18:23:10 +08:00
parent 6d9c3d8759
commit f4d9c07694
3 changed files with 62 additions and 56 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ workspace = true
[dependencies]
clap = { workspace = true }
regex = { workspace = true }
rustix = { workspace = true }
rustix = { workspace = true, features = ["fs", "process", "thread"] }
uucore = { workspace = true, features = ["entries", "signals", "process"] }
walkdir = { workspace = true }
+18 -8
View File
@@ -120,7 +120,7 @@ impl Teletype {
#[cfg(target_os = "linux")]
fn from_tty_nr_impl(tty_nr: u64, drivers: &[TtyDriverEntry]) -> Self {
use uucore::libc::{major, minor};
use rustix::fs::{major, minor};
if tty_nr == 0 {
return Self::Unknown;
@@ -843,7 +843,7 @@ unknown /dev/tty 4 1-63 console"#;
];
for (major, minor, expected) in test_cases {
let tty_nr = uucore::libc::makedev(major, minor);
let tty_nr = rustix::fs::makedev(major, minor);
let result = Teletype::from_tty_nr_impl(tty_nr, &parsed_entries);
assert_eq!(result, expected);
}
@@ -904,14 +904,14 @@ unknown /dev/tty 4 1-63 console"#;
#[test]
#[cfg(target_os = "linux")]
fn test_thread_ids() {
let main_tid = unsafe { uucore::libc::gettid() };
let main_tid = rustix::thread::gettid().as_raw_nonzero().get() as u64;
std::thread::spawn(move || {
let mut pid_entry = ProcessInformation::current_process_info().unwrap();
let thread_ids = pid_entry.thread_ids();
assert!(thread_ids.contains(&(main_tid as usize)));
let new_thread_tid = unsafe { uucore::libc::gettid() };
let new_thread_tid = rustix::thread::gettid().as_raw_nonzero().get() as u64;
assert!(thread_ids.contains(&(new_thread_tid as usize)));
})
.join()
@@ -939,14 +939,24 @@ unknown /dev/tty 4 1-63 console"#;
let mut pid_entry = ProcessInformation::current_process_info().unwrap();
assert_eq!(
pid_entry.ppid().unwrap(),
unsafe { uucore::libc::getppid() } as u64
rustix::process::getppid()
.map(|pid| pid.as_raw_nonzero().get() as u64)
.unwrap_or(0)
);
assert_eq!(
pid_entry.pgid().unwrap(),
unsafe { uucore::libc::getpgid(0) } as u64
rustix::process::getpgid(None)
.ok()
.map(|pid| pid.as_raw_nonzero().get() as u64)
.unwrap_or(0)
);
assert_eq!(
pid_entry.sid().unwrap(),
rustix::process::getsid(None)
.ok()
.map(|pid| pid.as_raw_nonzero().get() as u64)
.unwrap_or(0)
);
assert_eq!(pid_entry.sid().unwrap(), unsafe { uucore::libc::getsid(0) }
as u64);
}
#[test]
+43 -47
View File
@@ -6,15 +6,11 @@
// Common process matcher logic shared by pgrep, pkill and pidwait
use std::hash::Hash;
#[cfg(unix)]
use std::os::fd::AsRawFd;
use std::{collections::HashSet, io};
use clap::{arg, Arg, ArgAction, ArgMatches};
use regex::Regex;
#[cfg(unix)]
use uucore::libc::{getpgrp, getsid};
#[cfg(unix)]
use uucore::{
display::Quotable,
entries::{grp2gid, usr2uid},
@@ -91,24 +87,12 @@ pub fn get_match_settings(matches: &ArgMatches) -> UResult<Settings> {
.get_many::<u32>("group")
.map(|ids| ids.cloned().collect()),
pgroup: matches.get_many::<u64>("pgroup").map(|xs| {
xs.map(|pg| {
if *pg == 0 {
unsafe { getpgrp() as u64 }
} else {
*pg
}
})
.collect()
xs.map(|pg| if *pg == 0 { getpgrp() } else { *pg })
.collect()
}),
session: matches.get_many::<u64>("session").map(|xs| {
xs.map(|sid| {
if *sid == 0 {
unsafe { getsid(0) as u64 }
} else {
*sid
}
})
.collect()
xs.map(|sid| if *sid == 0 { getsid(0) } else { *sid })
.collect()
}),
cgroup: matches
.get_many::<String>("cgroup")
@@ -442,20 +426,31 @@ pub fn grp2gid(_name: &str) -> io::Result<u32> {
))
}
/// # Safety
///
/// Dummy implementation for unsupported platforms.
#[cfg(not(unix))]
pub unsafe fn getpgrp() -> u32 {
panic!("unsupported on this platform");
pub fn getpgrp() -> u64 {
#[cfg(unix)]
{
rustix::process::getpgrp().as_raw_nonzero().get() as u64
}
#[cfg(not(unix))]
{
0
}
}
/// # Safety
///
/// Dummy implementation for unsupported platforms.
#[cfg(not(unix))]
pub unsafe fn getsid(_pid: u32) -> u32 {
panic!("unsupported on this platform");
pub fn getsid(_pid: u32) -> u64 {
#[cfg(unix)]
{
rustix::process::getsid(None)
.ok()
.map(|pid: rustix::process::Pid| pid.as_raw_nonzero().get() as u64)
.unwrap_or(0)
}
#[cfg(not(unix))]
{
0
}
}
fn parse_uid_or_username(uid_or_username: &str) -> io::Result<u32> {
@@ -493,26 +488,27 @@ fn test_parse_pidfile_content_valid() {
#[cfg(unix)]
fn is_locked(file: &std::fs::File) -> bool {
// On Linux, fcntl and flock locks are independent, so need to check both
let mut flock_struct = uucore::libc::flock {
l_type: uucore::libc::F_RDLCK as uucore::libc::c_short,
l_whence: uucore::libc::SEEK_SET as uucore::libc::c_short,
l_start: 0,
l_len: 0,
l_pid: 0,
};
use rustix::fs::FlockOperation;
use std::os::fd::{AsRawFd, BorrowedFd};
let fd = file.as_raw_fd();
let result = unsafe { uucore::libc::fcntl(fd, uucore::libc::F_GETLK, &mut flock_struct) };
if result == 0 && flock_struct.l_type != uucore::libc::F_UNLCK as uucore::libc::c_short {
return true;
}
// Safety: The file descriptor is valid for the duration of this function
let borrowed_fd = unsafe { BorrowedFd::borrow_raw(fd) };
let result = unsafe { uucore::libc::flock(fd, uucore::libc::LOCK_SH | uucore::libc::LOCK_NB) };
if result == -1 && std::io::Error::last_os_error().kind() == std::io::ErrorKind::WouldBlock {
return true;
// Try to acquire a shared lock without blocking
match rustix::fs::flock(borrowed_fd, FlockOperation::NonBlockingLockShared) {
Ok(_) => {
let _ = rustix::fs::flock(borrowed_fd, FlockOperation::Unlock);
false
}
Err(e)
if e.kind() == io::ErrorKind::WouldBlock
|| e.kind() == io::ErrorKind::PermissionDenied =>
{
true
}
Err(_) => false,
}
false
}
#[cfg(not(unix))]