add types in preparation for non-blocking stdin
This commit is contained in:
parent
a9068f86f3
commit
a72a48f92b
4 changed files with 111 additions and 1 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -160,6 +160,7 @@ dependencies = [
|
|||
"libc",
|
||||
"regex",
|
||||
"regex-lite",
|
||||
"rustix",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tap",
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ itertools = "0.14.0"
|
|||
libc = { version = "0.2.180", features = ["extra_traits"] }
|
||||
regex = { version = "1.12.3", optional = true }
|
||||
regex-lite = { version = "0.1.9", optional = true }
|
||||
rustix = { version = "1.1.4", features = ["event", "fs"] }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
tap = "1.0.1"
|
||||
|
|
|
|||
106
src/daemon_io.rs
Normal file
106
src/daemon_io.rs
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
use std::{
|
||||
mem::ManuallyDrop,
|
||||
os::{
|
||||
fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd},
|
||||
unix::prelude::RawFd,
|
||||
},
|
||||
};
|
||||
|
||||
use rustix::{
|
||||
fs::{OFlags, fcntl_getfl, fcntl_setfl},
|
||||
io::Errno,
|
||||
};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
/// An [`OwnedFd`] that captures file status flags on init and restores them on:
|
||||
///
|
||||
/// - [`IntoRawFd`]
|
||||
/// - [`drop()`]
|
||||
#[derive(Debug)]
|
||||
pub struct OwnedFdWithFlags {
|
||||
fd: OwnedFd,
|
||||
oflags: OFlags,
|
||||
}
|
||||
|
||||
impl OwnedFdWithFlags {
|
||||
pub fn new(fd: OwnedFd) -> Result<Self, Errno> {
|
||||
let oflags = fcntl_getfl(&fd)?;
|
||||
Ok(Self { fd, oflags })
|
||||
}
|
||||
|
||||
/// If, for some ungodly reason, `fcntl(F_GETFL)` fails, then empty flags are used.
|
||||
/// Empty flags should not be restored on close.
|
||||
///
|
||||
/// I'm pretty sure this should never happen if the program is IO-safe.
|
||||
pub fn new_with_fallback(fd: OwnedFd) -> Self {
|
||||
let oflags = Self::get_flags_or_log(fd.as_fd());
|
||||
Self { fd, oflags }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedFdWithFlags {
|
||||
fn drop(&mut self) {
|
||||
self.restore_flags_or_log();
|
||||
}
|
||||
}
|
||||
|
||||
/// Private helpers.
|
||||
impl OwnedFdWithFlags {
|
||||
fn restore_flags_or_log(&self) {
|
||||
// As far as we can tell there's no such thing as a file with entirely empty
|
||||
// flags (at minimum, it needs read/write mode, right?).
|
||||
// So empty `oflags` is our sentinel that `fcntl(F_GETFL)` somehow failed.
|
||||
// Empty oflags is our sentinel that
|
||||
if self.oflags.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Err(e) = fcntl_setfl(&self.fd, self.oflags) {
|
||||
error!(
|
||||
"fcntl(F_SETFL) to restore flags {:?} on fd {:?} failed: {e}\nIO safety violation?",
|
||||
self.oflags, self.fd,
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
fn get_flags_or_log(fd: BorrowedFd) -> OFlags {
|
||||
fcntl_getfl(fd)
|
||||
.tap_err(|e| error!("fcntl(F_GETFL) failed on fd {fd:?}: {e}\nIO-safety violation?"))
|
||||
.unwrap_or(OFlags::empty())
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for OwnedFdWithFlags {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
AsRawFd::as_raw_fd(&self.fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for OwnedFdWithFlags {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.restore_flags_or_log();
|
||||
ManuallyDrop::new(self).fd.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for OwnedFdWithFlags {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
let fd = unsafe { OwnedFd::from_raw_fd(fd) };
|
||||
let oflags = Self::get_flags_or_log(fd.as_fd());
|
||||
Self { fd, oflags }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for OwnedFdWithFlags {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
AsFd::as_fd(&self.fd)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OwnedFd> for OwnedFdWithFlags {
|
||||
fn from(fd: OwnedFd) -> Self {
|
||||
let oflags = Self::get_flags_or_log(fd.as_fd());
|
||||
Self { fd, oflags }
|
||||
}
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ pub(crate) mod prelude {
|
|||
#[cfg(unix)]
|
||||
pub use fs_err::os::unix::fs::{FileExt, OpenOptionsExt};
|
||||
|
||||
pub use tap::{Pipe, Tap};
|
||||
pub use tap::{Pipe, Tap, TapFallible};
|
||||
|
||||
pub use tracing::{Level, debug, error, info, trace, warn};
|
||||
}
|
||||
|
|
@ -44,6 +44,8 @@ pub mod args;
|
|||
pub use args::{AppendCmd, Args};
|
||||
mod color;
|
||||
pub use color::{_CLI_ENABLE_COLOR, SHOULD_COLOR};
|
||||
mod daemon_io;
|
||||
pub use daemon_io::OwnedFdWithFlags;
|
||||
pub mod line;
|
||||
mod nixcmd;
|
||||
pub use line::Line;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue