Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src/uu/env/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ uucore = { workspace = true, features = ["signals"] }
fluent = { workspace = true }

[target.'cfg(unix)'.dependencies]
libc = { workspace = true }
nix = { workspace = true, features = ["signal"] }

[[bin]]
Expand Down
2 changes: 0 additions & 2 deletions src/uu/env/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ use native_int_str::{
Convert, NCvt, NativeIntStr, NativeIntString, NativeStr, from_native_int_representation_owned,
};
#[cfg(unix)]
use nix::libc;
#[cfg(unix)]
use nix::sys::signal::{
SigHandler::{SigDfl, SigIgn},
SigSet, SigmaskHow, Signal, signal, sigprocmask,
Expand Down
1 change: 1 addition & 0 deletions src/uu/mknod/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ doctest = false
clap = { workspace = true }
uucore = { workspace = true, features = ["mode", "fs"] }
fluent = { workspace = true }
libc = { workspace = true }
nix = { workspace = true }

[features]
Expand Down
2 changes: 1 addition & 1 deletion src/uu/mknod/src/mknod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// spell-checker:ignore (ToDO) parsemode makedev sysmacros perror IFBLK IFCHR IFIFO sflag

use clap::{Arg, ArgAction, Command, value_parser};
use nix::libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, mode_t};
use libc::{S_IRGRP, S_IROTH, S_IRUSR, S_IWGRP, S_IWOTH, S_IWUSR, mode_t};
use nix::sys::stat::{Mode, SFlag, mknod as nix_mknod, umask as nix_umask};

use uucore::display::Quotable;
Expand Down
1 change: 1 addition & 0 deletions src/uu/sort/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ foldhash = { workspace = true }
ctrlc = { workspace = true }

[target.'cfg(unix)'.dependencies]
libc = { workspace = true }
nix = { workspace = true, features = ["resource"] }

[dev-dependencies]
Expand Down
3 changes: 0 additions & 3 deletions src/uu/sort/src/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,8 +1410,6 @@ pub(crate) fn fd_soft_limit() -> Option<usize> {

#[cfg(unix)]
pub(crate) fn current_open_fd_count() -> Option<usize> {
use nix::libc;

fn count_dir(path: &str) -> Option<usize> {
let entries = std::fs::read_dir(path).ok()?;
let mut count = 0usize;
Expand Down Expand Up @@ -1770,7 +1768,6 @@ fn locale_failed_to_set() -> bool {

#[cfg(unix)]
fn locale_failed_to_set() -> bool {
use nix::libc;
unsafe { libc::setlocale(libc::LC_COLLATE, c"".as_ptr()).is_null() }
}

Expand Down
1 change: 1 addition & 0 deletions src/uu/stty/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ uucore = { workspace = true, features = ["parser"] }
fluent = { workspace = true }

[target.'cfg(unix)'.dependencies]
libc = { workspace = true }
nix = { workspace = true, features = ["ioctl", "term"] }

[[bin]]
Expand Down
10 changes: 5 additions & 5 deletions src/uu/stty/src/stty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ mod flags;
use crate::flags::AllFlags;
use crate::flags::COMBINATION_SETTINGS;
use clap::{Arg, ArgAction, ArgMatches, Command};
use nix::libc::{O_NONBLOCK, TIOCGWINSZ, TIOCSWINSZ, c_ushort};
use libc::{O_NONBLOCK, TIOCGWINSZ, TIOCSWINSZ, c_ushort};

#[cfg(all(
target_os = "linux",
not(target_arch = "powerpc"),
not(target_arch = "powerpc64")
))]
use nix::libc::{TCGETS2, termios2};
use libc::{TCGETS2, termios2};

use nix::sys::termios::{
ControlFlags, InputFlags, LocalFlags, OutputFlags, SetArg, SpecialCharacterIndices as S,
Expand Down Expand Up @@ -520,7 +520,7 @@ fn parse_rows_cols(arg: &str) -> Option<u16> {
/// - Returns `None` if format is invalid
fn parse_saved_state(arg: &str) -> Option<Vec<u32>> {
let parts: Vec<&str> = arg.split(':').collect();
let expected_parts = 4 + nix::libc::NCCS;
let expected_parts = 4 + libc::NCCS;

// GNU requires exactly the right number of parts for this platform
if parts.len() != expected_parts {
Expand Down Expand Up @@ -692,7 +692,7 @@ fn print_terminal_size(
{
// For some reason the normal nix Termios struct does not expose the line,
// so we get the underlying libc::termios struct to get that information.
let libc_termios: nix::libc::termios = termios.clone().into();
let libc_termios: libc::termios = termios.clone().into();
let line = libc_termios.c_line;
printer.print(&translate!("stty-output-line", "line" => line));
}
Expand Down Expand Up @@ -824,7 +824,7 @@ fn string_to_flag(option: &str) -> Option<AllFlags<'_>> {
None
}

fn control_char_to_string(cc: nix::libc::cc_t) -> nix::Result<String> {
fn control_char_to_string(cc: libc::cc_t) -> nix::Result<String> {
if cc == 0 {
return Ok(translate!("stty-output-undef"));
}
Expand Down
1 change: 1 addition & 0 deletions src/uucore/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ unic-langid = { workspace = true }
thiserror = { workspace = true }

[target.'cfg(unix)'.dependencies]
libc = { workspace = true }
nix = { workspace = true, features = [
"dir",
"fs",
Expand Down
1 change: 0 additions & 1 deletion src/uucore/src/lib/features/safe_traversal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use std::path::{Path, PathBuf};

use nix::dir::Dir;
use nix::fcntl::{OFlag, openat};
use nix::libc;
use nix::sys::stat::{FchmodatFlags, FileStat, Mode, fchmodat, fstatat, mkdirat};
use nix::unistd::{Gid, Uid, UnlinkatFlags, fchown, fchownat, unlinkat};
use os_display::Quotable;
Expand Down
170 changes: 167 additions & 3 deletions src/uucore/src/lib/features/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,179 @@

#[cfg(unix)]
use nix::errno::Errno;
#[cfg(any(target_os = "linux", target_os = "android"))]
use nix::libc;
#[cfg(unix)]
use nix::sys::signal::{
SaFlags, SigAction, SigHandler, SigHandler::SigDfl, SigHandler::SigIgn, SigSet, Signal,
Signal::SIGINT, Signal::SIGPIPE, sigaction, signal,
};

// ---------------------------------------------------------------------------
// Thin libc-based signal wrappers
//
// These replace nix's signal module for operations that rustix does not cover
// (sigaction, signal(), SigSet, SigHandler, sigprocmask).

Check failure on line 25 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sigprocmask' (file:'src/uucore/src/lib/features/signals.rs', line:25)
// ---------------------------------------------------------------------------
#[cfg(unix)]
pub mod csignal {

Check failure on line 28 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'csignal' (file:'src/uucore/src/lib/features/signals.rs', line:28)
use std::io;
use std::mem::MaybeUninit;

/// Signal handler disposition.
#[derive(Debug, Clone, Copy)]
pub enum SigHandler {
/// Default signal action.
SigDfl,
/// Ignore the signal.
SigIgn,
/// Call the given handler function.
Handler(extern "C" fn(libc::c_int)),
}

impl SigHandler {
fn to_sigaction_handler(self) -> libc::sighandler_t {

Check failure on line 44 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sighandler' (file:'src/uucore/src/lib/features/signals.rs', line:44)
match self {
Self::SigDfl => libc::SIG_DFL,
Self::SigIgn => libc::SIG_IGN,
Self::Handler(f) => f as libc::sighandler_t,

Check failure on line 48 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sighandler' (file:'src/uucore/src/lib/features/signals.rs', line:48)
}
}

fn from_sigaction_handler(handler: libc::sighandler_t) -> Self {

Check failure on line 52 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sighandler' (file:'src/uucore/src/lib/features/signals.rs', line:52)
if handler == libc::SIG_DFL {
Self::SigDfl
} else if handler == libc::SIG_IGN {
Self::SigIgn
} else {
// SAFETY: the handler is a valid function pointer set by a previous signal() call
Self::Handler(unsafe {
std::mem::transmute::<libc::sighandler_t, extern "C" fn(libc::c_int)>(handler)

Check failure on line 60 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sighandler' (file:'src/uucore/src/lib/features/signals.rs', line:60)
})
}
}
}

/// Wrapper around `libc::sigset_t`.

Check failure on line 66 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sigset' (file:'src/uucore/src/lib/features/signals.rs', line:66)
#[derive(Clone)]
pub struct SigSet(libc::sigset_t);

Check failure on line 68 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sigset' (file:'src/uucore/src/lib/features/signals.rs', line:68)

impl SigSet {
/// Creates an empty signal set.
pub fn empty() -> Self {
let mut set = MaybeUninit::<libc::sigset_t>::uninit();

Check failure on line 73 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sigset' (file:'src/uucore/src/lib/features/signals.rs', line:73)
// SAFETY: sigemptyset initializes the sigset_t

Check failure on line 74 in src/uucore/src/lib/features/signals.rs

View workflow job for this annotation

GitHub Actions / Style/spelling (ubuntu-latest, feat_os_unix)

ERROR: `cspell`: Unknown word 'sigemptyset' (file:'src/uucore/src/lib/features/signals.rs', line:74)
unsafe { libc::sigemptyset(set.as_mut_ptr()) };
Self(unsafe { set.assume_init() })
}

/// Creates a signal set with all signals.
pub fn all() -> Self {
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
// SAFETY: sigfillset initializes the sigset_t
unsafe { libc::sigfillset(set.as_mut_ptr()) };
Self(unsafe { set.assume_init() })
}

/// Adds a signal to the set.
pub fn add(&mut self, signum: libc::c_int) {
// SAFETY: sigaddset operates on a valid sigset_t
unsafe { libc::sigaddset(&raw mut self.0, signum) };
}

/// Returns a pointer to the inner sigset_t.
pub fn as_ptr(&self) -> *const libc::sigset_t {
&raw const self.0
}
}

/// Flags for `sigaction`.
pub mod sa_flags {
pub const SA_RESTART: libc::c_int = libc::SA_RESTART as libc::c_int;
}

/// How to modify the signal mask in `sigprocmask`.
#[derive(Debug, Clone, Copy)]
pub enum SigmaskHow {
/// Block the signals in the set.
Block,
/// Unblock the signals in the set.
Unblock,
/// Set the signal mask to the given set.
SetMask,
}

impl SigmaskHow {
fn as_libc(self) -> libc::c_int {
match self {
Self::Block => libc::SIG_BLOCK,
Self::Unblock => libc::SIG_UNBLOCK,
Self::SetMask => libc::SIG_SETMASK,
}
}
}

fn last_os_error() -> io::Error {
io::Error::last_os_error()
}

/// Set the disposition of a signal using `libc::signal()`.
///
/// Returns the previous signal handler.
///
/// # Safety
/// If `handler` is `SigHandler::Handler(f)`, the function `f` must be
/// async-signal-safe.
pub unsafe fn set_signal_handler(
signum: libc::c_int,
handler: SigHandler,
) -> io::Result<SigHandler> {
let prev = unsafe { libc::signal(signum, handler.to_sigaction_handler()) };
if prev == libc::SIG_ERR {
Err(last_os_error())
} else {
Ok(SigHandler::from_sigaction_handler(prev))
}
}

/// Install a signal action using `libc::sigaction()`.
///
/// # Safety
/// If the handler is a function pointer, it must be async-signal-safe.
pub unsafe fn set_signal_action(
signum: libc::c_int,
handler: SigHandler,
flags: libc::c_int,
mask: &SigSet,
) -> io::Result<()> {
let mut sa: libc::sigaction = unsafe { std::mem::zeroed() };
sa.sa_sigaction = handler.to_sigaction_handler();
sa.sa_flags = flags as _;
sa.sa_mask = mask.0;

let ret = unsafe { libc::sigaction(signum, &raw const sa, std::ptr::null_mut()) };
if ret == -1 {
Err(last_os_error())
} else {
Ok(())
}
}

/// Block/unblock/set signal mask using `libc::sigprocmask()`.
pub fn sigprocmask(
how: SigmaskHow,
set: Option<&SigSet>,
oldset: Option<&mut SigSet>,
) -> io::Result<()> {
let set_ptr = set.map_or(std::ptr::null(), SigSet::as_ptr);
let oldset_ptr = oldset.map_or(std::ptr::null_mut(), |s| &raw mut s.0);
let ret = unsafe { libc::sigprocmask(how.as_libc(), set_ptr, oldset_ptr) };
if ret == -1 {
Err(last_os_error())
} else {
Ok(())
}
}
}

/// The default signal value.
pub static DEFAULT_SIGNAL: usize = 15;

Expand Down Expand Up @@ -548,7 +713,6 @@
#[cfg(unix)]
#[allow(clippy::missing_safety_doc)]
pub unsafe extern "C" fn capture_startup_state() {
use nix::libc;
use std::mem::MaybeUninit;
use std::ptr;

Expand Down
2 changes: 0 additions & 2 deletions src/uucore/src/lib/mods/panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ pub fn mute_sigpipe_panic() {
/// variable. If set to "default", it restores SIGPIPE to SIG_DFL.
#[cfg(unix)]
pub fn preserve_inherited_sigpipe() {
use nix::libc;

// Check if parent specified that SIGPIPE should be default
if std::env::var_os("RUST_SIGPIPE").is_some_and(|v| v == "default") {
unsafe { libc::signal(libc::SIGPIPE, libc::SIG_DFL) };
Expand Down
Loading
Loading