diff --git a/src/uu/pgrep/Cargo.toml b/src/uu/pgrep/Cargo.toml index 7f71a9f2..5ea7f7ae 100644 --- a/src/uu/pgrep/Cargo.toml +++ b/src/uu/pgrep/Cargo.toml @@ -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 } diff --git a/src/uu/pgrep/src/process.rs b/src/uu/pgrep/src/process.rs index 5500a18c..6dce0479 100644 --- a/src/uu/pgrep/src/process.rs +++ b/src/uu/pgrep/src/process.rs @@ -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] diff --git a/src/uu/pgrep/src/process_matcher.rs b/src/uu/pgrep/src/process_matcher.rs index 3aa6c851..2d894f05 100644 --- a/src/uu/pgrep/src/process_matcher.rs +++ b/src/uu/pgrep/src/process_matcher.rs @@ -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 { .get_many::("group") .map(|ids| ids.cloned().collect()), pgroup: matches.get_many::("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::("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::("cgroup") @@ -445,17 +429,32 @@ pub fn grp2gid(_name: &str) -> io::Result { /// # 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 { @@ -493,26 +492,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, - }; - 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; - } + use rustix::fs::FlockOperation; + use std::os::fd::{AsRawFd, BorrowedFd}; - 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; + let fd = file.as_raw_fd(); + // Safety: The file descriptor is valid for the duration of this function + let borrowed_fd = unsafe { BorrowedFd::borrow_raw(fd) }; + + // 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))]