diff --git a/src/action.rs b/src/action.rs index 01b33a66..2bf089e6 100644 --- a/src/action.rs +++ b/src/action.rs @@ -76,7 +76,7 @@ impl Action { } } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum CopyTarget { Line, Commandline(SupportedShell), @@ -89,7 +89,7 @@ pub enum CopyTarget { EnvDiff, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SupportedShell { Bash, Sh, diff --git a/src/arch.rs b/src/arch.rs index 805d41ca..bfe3b2e6 100644 --- a/src/arch.rs +++ b/src/arch.rs @@ -3,13 +3,13 @@ use cfg_if::cfg_if; cfg_if! { if #[cfg(target_arch = "x86_64")] { pub mod x86_64; - pub(crate) use x86_64::*; + pub use x86_64::*; } else if #[cfg(target_arch = "aarch64")] { pub mod aarch64; - pub(crate) use aarch64::*; + pub use aarch64::*; } else if #[cfg(target_arch = "riscv64")] { pub mod riscv64; - pub(crate) use riscv64::*; + pub use riscv64::*; } else { compile_error!("unsupported architecture"); } diff --git a/src/bpf.rs b/src/bpf.rs index dad87b16..62e8e760 100644 --- a/src/bpf.rs +++ b/src/bpf.rs @@ -451,7 +451,7 @@ impl EbpfTracer { .as_ref() .map(|tx| filterable_event!(TraceeSpawn(child)).send_if_match(tx, self.filter)) .transpose()?; - if let TracerMode::Log { foreground: true } = &self.mode { + if matches!(&self.mode, TracerMode::Log { foreground: true }) { match tcsetpgrp(stdin(), child) { Ok(_) => {} Err(Errno::ENOTTY) => { diff --git a/src/bpf/interface.rs b/src/bpf/interface.rs index b5894594..d373201b 100644 --- a/src/bpf/interface.rs +++ b/src/bpf/interface.rs @@ -2,7 +2,7 @@ use enumflags2::bitflags; #[bitflags] #[repr(u32)] -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[allow(non_camel_case_types)] #[allow(clippy::upper_case_acronyms)] pub enum BpfEventFlags { diff --git a/src/bpf/process_tracker.rs b/src/bpf/process_tracker.rs index 5ccf9ce7..197bba02 100644 --- a/src/bpf/process_tracker.rs +++ b/src/bpf/process_tracker.rs @@ -46,11 +46,11 @@ impl ProcessTracker { } #[allow(unused)] - pub fn associated_events(&mut self, pid: Pid) -> &[u64] { + pub fn associated_events(&self, pid: Pid) -> &[u64] { &self.processes.get(&pid).unwrap().associated_events } - pub fn maybe_associated_events(&mut self, pid: Pid) -> Option<&[u64]> { + pub fn maybe_associated_events(&self, pid: Pid) -> Option<&[u64]> { self .processes .get(&pid) diff --git a/src/cli.rs b/src/cli.rs index 9dfb5391..b181cd5d 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -213,7 +213,7 @@ impl Cli { } pub fn generate_completions(shell: clap_complete::Shell) { - let mut cmd = Cli::command(); + let mut cmd = Self::command(); clap_complete::generate(shell, &mut cmd, env!("CARGO_CRATE_NAME"), &mut stdout()) } diff --git a/src/cli/config.rs b/src/cli/config.rs index 482397bb..9fd1113b 100644 --- a/src/cli/config.rs +++ b/src/cli/config.rs @@ -29,7 +29,7 @@ pub enum ConfigLoadError { } impl Config { - pub fn load(path: Option) -> Result { + pub fn load(path: Option) -> Result { let config_text = match path { Some(path) => std::fs::read_to_string(path)?, // if manually specified config doesn't exist, return a hard error None => { @@ -47,7 +47,7 @@ impl Config { } }; - let config: Config = toml::from_str(&config_text)?; + let config: Self = toml::from_str(&config_text)?; Ok(config) } } diff --git a/src/cli/options.rs b/src/cli/options.rs index f64db39c..9fab265b 100644 --- a/src/cli/options.rs +++ b/src/cli/options.rs @@ -2,7 +2,7 @@ use clap::ValueEnum; use serde::{Deserialize, Serialize}; use strum::Display; -#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Display)] +#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Display)] #[strum(serialize_all = "kebab-case")] pub enum Color { Auto, @@ -10,7 +10,7 @@ pub enum Color { Never, } -#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Display, Default, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Display, Default, Deserialize, Serialize)] #[strum(serialize_all = "kebab-case")] pub enum SeccompBpf { #[default] @@ -19,7 +19,9 @@ pub enum SeccompBpf { Off, } -#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Display, Default, Deserialize, Serialize)] +#[derive( + Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Display, Default, Deserialize, Serialize, +)] #[strum(serialize_all = "kebab-case")] pub enum ActivePane { #[default] @@ -27,7 +29,7 @@ pub enum ActivePane { Events, } -#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Display, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, ValueEnum, PartialEq, Eq, Display, Deserialize, Serialize)] #[strum(serialize_all = "kebab-case")] pub enum ExportFormat { // https://jsonlines.org/ diff --git a/src/cmdbuilder.rs b/src/cmdbuilder.rs index 3c95fdc0..4a173382 100644 --- a/src/cmdbuilder.rs +++ b/src/cmdbuilder.rs @@ -66,7 +66,7 @@ fn get_shell() -> String { /// `CommandBuilder` is used to prepare a command to be spawned into a pty. /// The interface is intentionally similar to that of `std::process::Command`. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub struct CommandBuilder { args: Vec, cwd: Option, diff --git a/src/event.rs b/src/event.rs index 52247a35..17c34449 100644 --- a/src/event.rs +++ b/src/event.rs @@ -73,9 +73,9 @@ impl Hash for FriendlyError { fn hash(&self, state: &mut H) { core::mem::discriminant(self).hash(state); match self { - FriendlyError::InspectError(e) => (*e as i32).hash(state), + Self::InspectError(e) => (*e as i32).hash(state), #[cfg(feature = "ebpf")] - FriendlyError::Bpf(e) => e.hash(state), + Self::Bpf(e) => e.hash(state), } } } @@ -109,9 +109,9 @@ pub enum OutputMsg { impl AsRef for OutputMsg { fn as_ref(&self) -> &str { match self { - OutputMsg::Ok(s) => s.as_ref(), - OutputMsg::PartialOk(s) => s.as_ref(), - OutputMsg::Err(e) => <&'static str>::from(e), + Self::Ok(s) => s.as_ref(), + Self::PartialOk(s) => s.as_ref(), + Self::Err(e) => <&'static str>::from(e), } } } @@ -122,9 +122,9 @@ impl Serialize for OutputMsg { S: serde::Serializer, { match self { - OutputMsg::Ok(s) => s.serialize(serializer), - OutputMsg::PartialOk(s) => s.serialize(serializer), - OutputMsg::Err(e) => <&'static str>::from(e).serialize(serializer), + Self::Ok(s) => s.serialize(serializer), + Self::PartialOk(s) => s.serialize(serializer), + Self::Err(e) => <&'static str>::from(e).serialize(serializer), } } } @@ -132,9 +132,9 @@ impl Serialize for OutputMsg { impl Display for OutputMsg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - OutputMsg::Ok(msg) => write!(f, "{msg:?}"), - OutputMsg::PartialOk(msg) => write!(f, "{:?}", cli::theme::THEME.inline_error.style(msg)), - OutputMsg::Err(e) => Display::fmt(&cli::theme::THEME.inline_error.style(&e), f), + Self::Ok(msg) => write!(f, "{msg:?}"), + Self::PartialOk(msg) => write!(f, "{:?}", cli::theme::THEME.inline_error.style(msg)), + Self::Err(e) => Display::fmt(&cli::theme::THEME.inline_error.style(&e), f), } } } @@ -153,22 +153,22 @@ impl From for OutputMsg { impl OutputMsg { pub fn not_ok(&self) -> bool { - !matches!(self, OutputMsg::Ok(_)) + !matches!(self, Self::Ok(_)) } pub fn is_ok_and(&self, predicate: impl FnOnce(&str) -> bool) -> bool { match self { - OutputMsg::Ok(s) => predicate(s), - OutputMsg::PartialOk(_) => false, - OutputMsg::Err(_) => false, + Self::Ok(s) => predicate(s), + Self::PartialOk(_) => false, + Self::Err(_) => false, } } pub fn is_err_or(&self, predicate: impl FnOnce(&str) -> bool) -> bool { match self { - OutputMsg::Ok(s) => predicate(s), - OutputMsg::PartialOk(_) => true, - OutputMsg::Err(_) => true, + Self::Ok(s) => predicate(s), + Self::PartialOk(_) => true, + Self::Err(_) => true, } } @@ -176,26 +176,24 @@ impl OutputMsg { pub fn join(&self, path: impl AsRef) -> Self { let path = path.as_ref(); match self { - OutputMsg::Ok(s) => OutputMsg::Ok(cached_string(format!("{s}/{path}"))), - OutputMsg::PartialOk(s) => OutputMsg::PartialOk(cached_string(format!("{s}/{path}"))), - OutputMsg::Err(s) => { - OutputMsg::PartialOk(cached_string(format!("{}/{path}", <&'static str>::from(s)))) - } + Self::Ok(s) => Self::Ok(cached_string(format!("{s}/{path}"))), + Self::PartialOk(s) => Self::PartialOk(cached_string(format!("{s}/{path}"))), + Self::Err(s) => Self::PartialOk(cached_string(format!("{}/{path}", <&'static str>::from(s)))), } } /// Escape the content for bash shell if it is not error pub fn tui_bash_escaped_with_style(&self, style: Style) -> Span<'static> { match self { - OutputMsg::Ok(s) => { + Self::Ok(s) => { shell_quote::QuoteRefExt::::quoted(s.as_str(), shell_quote::Bash).set_style(style) } - OutputMsg::PartialOk(s) => { + Self::PartialOk(s) => { shell_quote::QuoteRefExt::::quoted(s.as_str(), shell_quote::Bash) .set_style(style) .patch_style(THEME.inline_tracer_error) } - OutputMsg::Err(e) => <&'static str>::from(e).set_style(THEME.inline_tracer_error), + Self::Err(e) => <&'static str>::from(e).set_style(THEME.inline_tracer_error), } } @@ -205,14 +203,14 @@ impl OutputMsg { style: owo_colors::Style, ) -> Either { match self { - OutputMsg::Ok(s) => Either::Left(style.style(shell_quote::QuoteRefExt::::quoted( + Self::Ok(s) => Either::Left(style.style(shell_quote::QuoteRefExt::::quoted( s.as_str(), shell_quote::Bash, ))), - OutputMsg::PartialOk(s) => Either::Left(cli::theme::THEME.inline_error.style( + Self::PartialOk(s) => Either::Left(cli::theme::THEME.inline_error.style( shell_quote::QuoteRefExt::::quoted(s.as_str(), shell_quote::Bash), )), - OutputMsg::Err(e) => Either::Right( + Self::Err(e) => Either::Right( cli::theme::THEME .inline_error .style(<&'static str>::from(e)), @@ -223,27 +221,27 @@ impl OutputMsg { /// Escape the content for bash shell if it is not error pub fn bash_escaped(&self) -> Cow<'static, str> { match self { - OutputMsg::Ok(s) | OutputMsg::PartialOk(s) => Cow::Owned(shell_quote::QuoteRefExt::quoted( + Self::Ok(s) | Self::PartialOk(s) => Cow::Owned(shell_quote::QuoteRefExt::quoted( s.as_str(), shell_quote::Bash, )), - OutputMsg::Err(e) => Cow::Borrowed(<&'static str>::from(e)), + Self::Err(e) => Cow::Borrowed(<&'static str>::from(e)), } } pub fn tui_styled(&self, style: Style) -> Span { match self { - OutputMsg::Ok(s) => (*s).set_style(style), - OutputMsg::PartialOk(s) => (*s).set_style(THEME.inline_tracer_error), - OutputMsg::Err(e) => <&'static str>::from(e).set_style(THEME.inline_tracer_error), + Self::Ok(s) => (*s).set_style(style), + Self::PartialOk(s) => (*s).set_style(THEME.inline_tracer_error), + Self::Err(e) => <&'static str>::from(e).set_style(THEME.inline_tracer_error), } } pub fn cli_styled(&self, style: owo_colors::Style) -> Either { match self { - OutputMsg::Ok(s) => Either::Left(s.style(style)), - OutputMsg::PartialOk(s) => Either::Left(s.style(cli::theme::THEME.inline_error)), - OutputMsg::Err(e) => Either::Right( + Self::Ok(s) => Either::Left(s.style(style)), + Self::PartialOk(s) => Either::Left(s.style(cli::theme::THEME.inline_error)), + Self::Err(e) => Either::Right( cli::theme::THEME .inline_error .style(<&'static str>::from(e)), @@ -263,11 +261,9 @@ impl OutputMsg { } } match self { - OutputMsg::Ok(s) => Either::Left(style.style(DebugAsDisplay(s))), - OutputMsg::PartialOk(s) => { - Either::Left(cli::theme::THEME.inline_error.style(DebugAsDisplay(s))) - } - OutputMsg::Err(e) => Either::Right( + Self::Ok(s) => Either::Left(style.style(DebugAsDisplay(s))), + Self::PartialOk(s) => Either::Left(cli::theme::THEME.inline_error.style(DebugAsDisplay(s))), + Self::Err(e) => Either::Right( cli::theme::THEME .inline_error .style(<&'static str>::from(e)), @@ -296,17 +292,17 @@ pub enum TracerMessage { impl From for TracerMessage { fn from(event: TracerEvent) -> Self { - TracerMessage::Event(event) + Self::Event(event) } } impl From for TracerMessage { fn from(update: ProcessStateUpdateEvent) -> Self { - TracerMessage::StateUpdate(update) + Self::StateUpdate(update) } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct TracerEvent { pub details: TracerEventDetails, pub id: u64, @@ -333,7 +329,7 @@ impl From for TracerEvent { } } -#[derive(Debug, Clone, PartialEq, FilterableEnum)] +#[derive(Debug, Clone, PartialEq, Eq, FilterableEnum)] #[filterable_enum(kind_extra_derive=ValueEnum, kind_extra_derive=Display, kind_extra_attrs="strum(serialize_all = \"kebab-case\")")] pub enum TracerEventDetails { Info(TracerEventMessage), @@ -352,13 +348,13 @@ pub enum TracerEventDetails { }, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct TracerEventMessage { pub pid: Option, pub msg: String, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ExecEvent { pub pid: Pid, pub cwd: OutputMsg, @@ -372,7 +368,7 @@ pub struct ExecEvent { pub result: i64, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct RuntimeModifier { pub show_env: bool, pub show_cwd: bool, @@ -435,7 +431,7 @@ impl TracerEventDetails { }; let mut line = match self { - TracerEventDetails::Info(TracerEventMessage { ref msg, pid }) => chain!( + Self::Info(TracerEventMessage { ref msg, pid }) => chain!( pid .map(|p| [p.to_string().set_style(THEME.pid_in_msg)]) .unwrap_or_default(), @@ -443,7 +439,7 @@ impl TracerEventDetails { [": ".into(), msg.clone().set_style(THEME.tracer_info)] ) .collect(), - TracerEventDetails::Warning(TracerEventMessage { ref msg, pid }) => chain!( + Self::Warning(TracerEventMessage { ref msg, pid }) => chain!( pid .map(|p| [p.to_string().set_style(THEME.pid_in_msg)]) .unwrap_or_default(), @@ -451,7 +447,7 @@ impl TracerEventDetails { [": ".into(), msg.clone().set_style(THEME.tracer_warning)] ) .collect(), - TracerEventDetails::Error(TracerEventMessage { ref msg, pid }) => chain!( + Self::Error(TracerEventMessage { ref msg, pid }) => chain!( pid .map(|p| [p.to_string().set_style(THEME.pid_in_msg)]) .unwrap_or_default(), @@ -459,7 +455,7 @@ impl TracerEventDetails { [": ".into(), msg.clone().set_style(THEME.tracer_error)] ) .collect(), - TracerEventDetails::NewChild { ppid, pcomm, pid } => [ + Self::NewChild { ppid, pcomm, pid } => [ Some(ppid.to_string().set_style(THEME.pid_success)), event_status.map(|s| <&'static str>::from(s).into()), Some(format!("<{}>", pcomm).set_style(THEME.comm)), @@ -470,7 +466,7 @@ impl TracerEventDetails { .into_iter() .flatten() .collect(), - TracerEventDetails::Exec(exec) => { + Self::Exec(exec) => { let ExecEvent { pid, cwd, @@ -654,12 +650,12 @@ impl TracerEventDetails { Line::default().spans(spans) } - TracerEventDetails::TraceeExit { signal, exit_code } => format!( + Self::TraceeExit { signal, exit_code } => format!( "tracee exit: signal: {:?}, exit_code: {}", signal, exit_code ) .into(), - TracerEventDetails::TraceeSpawn(pid) => format!("tracee spawned: {}", pid).into(), + Self::TraceeSpawn(pid) => format!("tracee spawned: {}", pid).into(), }; let mut cwd_mask = None; let mut env_mask = None; @@ -695,14 +691,14 @@ impl TracerEventDetails { modifier_args: &ModifierArgs, rt_modifier: RuntimeModifier, ) -> Cow<'a, str> { - if let CopyTarget::Line = target { + if CopyTarget::Line == target { return self .to_event_line(baseline, false, modifier_args, rt_modifier, None, false) .to_string() .into(); } // Other targets are only available for Exec events - let TracerEventDetails::Exec(event) = self else { + let Self::Exec(event) = self else { panic!("Copy target {:?} is only available for Exec events", target); }; let mut modifier_args = ModifierArgs::default(); @@ -846,7 +842,7 @@ macro_rules! filterable_event { pub(crate) use filterable_event; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum ProcessStateUpdate { Exit(ProcessExit), BreakPointHit(BreakPointHit), @@ -856,14 +852,14 @@ pub enum ProcessStateUpdate { DetachError { hit: BreakPointHit, error: Errno }, } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct ProcessStateUpdateEvent { pub update: ProcessStateUpdate, pub pid: Pid, pub ids: Vec, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum EventStatus { // exec status ExecENOENT, diff --git a/src/export.rs b/src/export.rs index 66be74d5..d3d3ae36 100644 --- a/src/export.rs +++ b/src/export.rs @@ -12,7 +12,7 @@ use crate::{ #[derive(Debug, Clone, Serialize)] #[serde(tag = "result", content = "value", rename_all = "kebab-case")] -pub enum JsonResult { +pub enum JsonResult { Success(T), Error(String), } diff --git a/src/log.rs b/src/log.rs index 0c4a1472..1f4d627d 100644 --- a/src/log.rs +++ b/src/log.rs @@ -28,7 +28,7 @@ pub use tracing::*; use crate::{cli::config::project_directory, tui::restore_tui}; lazy_static! { - pub static ref PROJECT_NAME: String = env!("CARGO_CRATE_NAME").to_uppercase().to_string(); + pub static ref PROJECT_NAME: String = env!("CARGO_CRATE_NAME").to_uppercase(); pub static ref DATA_FOLDER: Option = std::env::var(format!("{}_DATA", PROJECT_NAME.clone())) .ok() diff --git a/src/main.rs b/src/main.rs index 8e3b7e61..57c19ff0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,19 @@ +#![warn( + clippy::all, + // clippy::pedantic, + clippy::nursery, +)] +#![allow( + clippy::option_if_let_else, + clippy::missing_const_for_fn, + clippy::significant_drop_tightening, + clippy::cognitive_complexity, // FIXME + clippy::large_stack_frames, // In generated bpf skel, not really used to store on stack. + clippy::future_not_send, // We are not a library for now. + clippy::branches_sharing_code, + clippy::non_send_fields_in_send_ty, // In bpf skel, maybe open an issue in libbpf-rs? +)] + mod action; mod arch; #[cfg(feature = "ebpf")] @@ -341,12 +357,7 @@ fn is_current_kernel_greater_than(min_support: (u32, u32)) -> color_eyre::Result let utsname = nix::sys::utsname::uname()?; let kstr = utsname.release().as_bytes(); let pos = kstr.iter().position(|&c| c != b'.' && !c.is_ascii_digit()); - let kver = if let Some(pos) = pos { - let (s, _) = kstr.split_at(pos); - s - } else { - kstr - }; + let kver = pos.map_or(kstr, |pos| kstr.split_at(pos).0); let mut kvers = kver.split(|&c| c == b'.'); let Some(major) = kvers.next().and_then(atoi::) else { bail!("Failed to parse kernel major ver!") diff --git a/src/printer.rs b/src/printer.rs index 0541fd91..b1c2de54 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -43,7 +43,7 @@ pub enum FdPrintFormat { None, } -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)] pub enum ColorLevel { Less, Normal, @@ -69,7 +69,7 @@ pub struct PrinterArgs { impl PrinterArgs { pub fn from_cli(tracing_args: &LogModeArgs, modifier_args: &ModifierArgs) -> Self { - PrinterArgs { + Self { trace_comm: !tracing_args.no_show_comm, trace_argv: !tracing_args.no_show_argv && !tracing_args.show_cmdline, trace_env: match ( @@ -176,11 +176,11 @@ pub struct ListPrinter { impl ListPrinter { pub fn new(color: ColorLevel) -> Self { if color > ColorLevel::Normal { - ListPrinter { + Self { style: Style::new().bright_white().bold(), } } else { - ListPrinter { + Self { style: Style::new(), } } @@ -245,7 +245,7 @@ pub struct Printer { impl Printer { pub fn new(args: PrinterArgs, baseline: Arc) -> Self { - Printer { args, baseline } + Self { args, baseline } } thread_local! { @@ -253,7 +253,7 @@ impl Printer { } pub fn init_thread_local(&self, output: Option>) { - Printer::OUT.with(|out| { + Self::OUT.with(|out| { *out.borrow_mut() = output; }); } @@ -411,6 +411,7 @@ impl Printer { // 2. state.exec_data is Some // Defer the warnings so that they are printed after the main message + #[allow(clippy::collection_is_never_read)] let mut _deferred_warnings = vec![]; Self::OUT.with_borrow_mut(|out| { diff --git a/src/proc.rs b/src/proc.rs index c81e9906..bdbc44b1 100644 --- a/src/proc.rs +++ b/src/proc.rs @@ -60,7 +60,7 @@ pub fn read_exe(pid: Pid) -> std::io::Result { Ok(cached_str(&buf.to_string_lossy())) } -#[derive(Debug, Clone, Default, PartialEq, Serialize)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize)] pub struct FileDescriptorInfoCollection { #[serde(flatten)] pub fdinfo: BTreeMap, @@ -106,7 +106,7 @@ impl FileDescriptorInfoCollection { } } -#[derive(Debug, Clone, PartialEq, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct FileDescriptorInfo { pub fd: c_int, pub path: OutputMsg, @@ -120,11 +120,11 @@ pub struct FileDescriptorInfo { } impl FileDescriptorInfo { - pub fn not_same_file_as(&self, other: &FileDescriptorInfo) -> bool { + pub fn not_same_file_as(&self, other: &Self) -> bool { !self.same_file_as(other) } - pub fn same_file_as(&self, other: &FileDescriptorInfo) -> bool { + pub fn same_file_as(&self, other: &Self) -> bool { self.ino == other.ino && self.mnt_id == other.mnt_id } } @@ -221,7 +221,7 @@ fn get_mountinfo_by_mnt_id(pid: Pid, mnt_id: c_int) -> color_eyre::Result) -> fmt::Result { match self { - Interpreter::None => write!(f, "{}", "none".bold()), - Interpreter::Shebang(s) => write!(f, "{:?}", s), - Interpreter::ExecutableUnaccessible => { + Self::None => write!(f, "{}", "none".bold()), + Self::Shebang(s) => write!(f, "{:?}", s), + Self::ExecutableUnaccessible => { write!(f, "{}", "executable unaccessible".red().bold()) } - Interpreter::Error(e) => write!(f, "({}: {})", "err".red().bold(), e.red().bold()), + Self::Error(e) => write!(f, "({}: {})", "err".red().bold(), e.red().bold()), } } } @@ -385,7 +385,7 @@ pub fn cached_string(s: String) -> ArcStr { cache.get_or_insert_owned(s) } -#[derive(Debug, Clone, PartialEq, Serialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize)] pub struct EnvDiff { pub added: BTreeMap, pub removed: BTreeSet, @@ -420,7 +420,7 @@ pub fn diff_env( } EnvDiff { added, - removed: removed.into_iter().map(|x| x.to_owned()).collect(), + removed: removed.into_iter().collect(), modified, } } diff --git a/src/pty.rs b/src/pty.rs index eb22c50a..dc3f2117 100644 --- a/src/pty.rs +++ b/src/pty.rs @@ -64,7 +64,7 @@ pub struct PtySize { impl Default for PtySize { fn default() -> Self { - PtySize { + Self { rows: 24, cols: 80, pixel_width: 0, @@ -181,7 +181,7 @@ impl ExitStatus { } impl From for ExitStatus { - fn from(status: std::process::ExitStatus) -> ExitStatus { + fn from(status: std::process::ExitStatus) -> Self { #[cfg(unix)] { use std::os::unix::process::ExitStatusExt; @@ -195,7 +195,7 @@ impl From for ExitStatus { signame.to_string_lossy().to_string() }; - return ExitStatus { + return Self { code: status.code().map(|c| c as u32).unwrap_or(1), signal: Some(signal), }; @@ -207,7 +207,7 @@ impl From for ExitStatus { .map(|c| c as u32) .unwrap_or_else(|| if status.success() { 0 } else { 1 }); - ExitStatus { code, signal: None } + Self { code, signal: None } } } @@ -243,11 +243,11 @@ pub trait PtySystem { impl Child for std::process::Child { fn try_wait(&mut self) -> IoResult> { - std::process::Child::try_wait(self).map(|s| s.map(Into::into)) + Self::try_wait(self).map(|s| s.map(Into::into)) } fn wait(&mut self) -> IoResult { - std::process::Child::wait(self).map(Into::into) + Self::wait(self).map(Into::into) } fn process_id(&self) -> Pid { @@ -308,7 +308,7 @@ impl ChildKiller for std::process::Child { // it's still alive after a grace period, so proceed with a kill } - std::process::Child::kill(self) + Self::kill(self) } fn clone_killer(&self) -> Box { diff --git a/src/regex.rs b/src/regex.rs index 853d5f3b..c4a22654 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -3,17 +3,17 @@ use regex_cursor::Cursor; use crate::event::OutputMsg; -pub(crate) trait BidirectionalIterator: Iterator { +pub trait BidirectionalIterator: Iterator { fn prev(&mut self) -> Option; } -pub(crate) trait IntoBidirectionalIterator { +pub trait IntoBidirectionalIterator { type Iter: BidirectionalIterator; fn into_bidirectional_iter(self) -> Self::Iter; } -pub(crate) struct BidirectionalIter<'a, T> { +pub struct BidirectionalIter<'a, T> { slice: &'a [T], index: BidirectionalIterIndex, } @@ -113,7 +113,7 @@ enum BidirectionalInterspersedIterIndex { End, } -pub(crate) struct BidirectionalInterspersedIter<'a, T> { +pub struct BidirectionalInterspersedIter<'a, T> { slice: &'a [T], index: BidirectionalInterspersedIterIndex, separator: &'a T, diff --git a/src/tracer.rs b/src/tracer.rs index 9662bc33..83cc9e22 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -98,7 +98,7 @@ pub enum TracerMode { Log { foreground: bool }, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct BreakPointHit { pub bid: u32, pub pid: Pid, @@ -182,8 +182,10 @@ impl Tracer { baseline.clone(), ), delay: { + #[allow(clippy::useless_let_if_seq)] let mut default = Duration::from_micros(1); #[cfg(feature = "seccomp-bpf")] + #[allow(clippy::useless_let_if_seq)] if seccomp_bpf == SeccompBpf::On { default = Duration::from_micros(500); } @@ -333,7 +335,7 @@ impl Tracer { self.store.write().unwrap().insert(root_child_state); } // Set foreground process group of the terminal - if let TracerMode::Log { foreground: true } = &self.mode { + if matches!(&self.mode, TracerMode::Log { foreground: true }) { match tcsetpgrp(stdin(), root_child) { Ok(_) => {} Err(Errno::ENOTTY) => { @@ -485,15 +487,16 @@ impl Tracer { let mut store = self.store.write().unwrap(); if let Some(state) = store.get_current_mut(pid) { state.status = ProcessStatus::Exited(ProcessExit::Code(code)); - let mut should_exit = false; - if pid == root_child { + let should_exit = if pid == root_child { filterable_event!(TraceeExit { signal: None, exit_code: code, }) .send_if_match(&self.msg_tx, self.filter)?; - should_exit = true; - } + true + } else { + false + }; let associated_events = state.associated_events.clone(); if !associated_events.is_empty() { self.msg_tx.send( @@ -558,6 +561,7 @@ impl Tracer { state.status = ProcessStatus::PtraceForkEventReceived; state.ppid = Some(pid); store.insert(state); + drop(store); } // Resume parent self.seccomp_aware_cont(pid)?; @@ -798,7 +802,6 @@ impl Tracer { let mut store = self.store.write().unwrap(); let p = store.get_current_mut(pid).unwrap(); p.presyscall = !p.presyscall; - let regs = match ptrace_getregs(pid) { Ok(regs) => regs, Err(Errno::ESRCH) => { @@ -820,7 +823,7 @@ impl Tracer { } if self.filter.intersects(TracerEventDetailsKind::Exec) { // TODO: optimize, we don't need to collect exec event for log mode - let event = TracerEvent::from(TracerEventDetails::Exec(Tracer::collect_exec_event( + let event = TracerEvent::from(TracerEventDetails::Exec(Self::collect_exec_event( &self.baseline.env, p, exec_result, @@ -1228,7 +1231,7 @@ impl Tracer { error!("Failed to suspend {pid}'s seccomp filter: {errno}"); return Err(errno); } else { - trace!("suspended {pid}'s seccomp filter successfully") + trace!("suspended {pid}'s seccomp filter successfully"); } } } diff --git a/src/tracer/state.rs b/src/tracer/state.rs index a238e27d..2274a075 100644 --- a/src/tracer/state.rs +++ b/src/tracer/state.rs @@ -46,13 +46,13 @@ pub struct ProcessState { pub pending_detach: Option, } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ProcessExit { Code(i32), Signal(Signal), } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Eq)] pub enum ProcessStatus { Initialized, SigstopReceived, @@ -139,7 +139,7 @@ impl ProcessState { } } -#[derive(Debug, Clone, Copy, PartialEq, IntoStaticStr)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, IntoStaticStr)] pub enum BreakPointStop { SyscallEnter, SyscallExit, @@ -148,8 +148,8 @@ pub enum BreakPointStop { impl BreakPointStop { pub fn toggle(&mut self) { *self = match self { - BreakPointStop::SyscallEnter => BreakPointStop::SyscallExit, - BreakPointStop::SyscallExit => BreakPointStop::SyscallEnter, + Self::SyscallEnter => Self::SyscallExit, + Self::SyscallExit => Self::SyscallEnter, } } } @@ -189,18 +189,18 @@ pub struct BreakPoint { impl BreakPointPattern { pub fn pattern(&self) -> &str { match self { - BreakPointPattern::ArgvRegex(regex) => regex.editable.as_str(), - BreakPointPattern::InFilename(filename) => filename, + Self::ArgvRegex(regex) => regex.editable.as_str(), + Self::InFilename(filename) => filename, // Unwrap is fine since user inputs the filename as str - BreakPointPattern::ExactFilename(filename) => filename, + Self::ExactFilename(filename) => filename, } } pub fn to_editable(&self) -> String { match self { - BreakPointPattern::ArgvRegex(regex) => format!("argv-regex:{}", regex.editable), - BreakPointPattern::InFilename(filename) => format!("in-filename:{}", filename), - BreakPointPattern::ExactFilename(filename) => { + Self::ArgvRegex(regex) => format!("argv-regex:{}", regex.editable), + Self::InFilename(filename) => format!("in-filename:{}", filename), + Self::ExactFilename(filename) => { format!("exact-filename:{}", filename) } } @@ -224,7 +224,7 @@ impl BreakPointPattern { pub fn matches(&self, argv: Option<&[OutputMsg]>, filename: &OutputMsg) -> bool { match self { - BreakPointPattern::ArgvRegex(regex) => { + Self::ArgvRegex(regex) => { let Some(argv) = argv else { return false; }; @@ -236,13 +236,13 @@ impl BreakPointPattern { &mut regex_cursor::Input::new(argv), ) } - BreakPointPattern::InFilename(pattern) => { + Self::InFilename(pattern) => { let OutputMsg::Ok(filename) = filename else { return false; }; filename.contains(pattern) } - BreakPointPattern::ExactFilename(path) => { + Self::ExactFilename(path) => { let OutputMsg::Ok(filename) = filename else { return false; }; diff --git a/src/tui.rs b/src/tui.rs index 5d9dd474..075eda91 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -102,22 +102,22 @@ impl Tui { self.cancel(); self.cancellation_token = CancellationToken::new(); let _cancellation_token = self.cancellation_token.clone(); - let _event_tx = self.event_tx.clone(); + let event_tx = self.event_tx.clone(); self.task = tokio::spawn(async move { let mut reader = crossterm::event::EventStream::new(); let mut render_interval = tokio::time::interval(render_delay); - _event_tx.send(Event::Init).unwrap(); + event_tx.send(Event::Init).unwrap(); loop { let render_delay = render_interval.tick(); let crossterm_event = reader.next().fuse(); let tracer_event = tracer_rx.recv(); tokio::select! { - _ = _cancellation_token.cancelled() => { + () = _cancellation_token.cancelled() => { break; } Some(tracer_event) = tracer_event => { trace!("TUI event: tracer message!"); - _event_tx.send(Event::Tracer(tracer_event)).unwrap(); + event_tx.send(Event::Tracer(tracer_event)).unwrap(); } Some(event) = crossterm_event => { #[cfg(debug_assertions)] @@ -127,11 +127,11 @@ impl Tui { match evt { CrosstermEvent::Key(key) => { if key.kind == KeyEventKind::Press { - _event_tx.send(Event::Key(key)).unwrap(); + event_tx.send(Event::Key(key)).unwrap(); } }, CrosstermEvent::Resize(cols, rows) => { - _event_tx.send(Event::Resize(Size { + event_tx.send(Event::Resize(Size { width: cols, height: rows, })).unwrap(); @@ -140,13 +140,13 @@ impl Tui { } } Err(_) => { - _event_tx.send(Event::Error).unwrap(); + event_tx.send(Event::Error).unwrap(); } } }, _ = render_delay => { // log::trace!("TUI event: Render!"); - _event_tx.send(Event::Render).unwrap(); + event_tx.send(Event::Render).unwrap(); }, } } diff --git a/src/tui/app.rs b/src/tui/app.rs index 317b30fe..439c20f9 100644 --- a/src/tui/app.rs +++ b/src/tui/app.rs @@ -67,7 +67,7 @@ use super::{ Tui, }; -#[derive(Debug, Clone, Copy, PartialEq, Default, ValueEnum, Display, Deserialize, Serialize)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, ValueEnum, Display, Deserialize, Serialize)] #[strum(serialize_all = "kebab-case")] pub enum AppLayout { #[default] @@ -220,8 +220,8 @@ impl App { self.popup = None; } ActivePopup::ViewDetails(state) => { - if let ControlFlow::Break(()) = - state.handle_key_event(ke, self.clipboard.as_mut())? + if ControlFlow::Break(()) + == state.handle_key_event(ke, self.clipboard.as_mut())? { self.popup = None; } diff --git a/src/tui/error_popup.rs b/src/tui/error_popup.rs index 5ef10c1c..31efa4b2 100644 --- a/src/tui/error_popup.rs +++ b/src/tui/error_popup.rs @@ -20,7 +20,7 @@ pub struct InfoPopupState { } impl InfoPopupState { - pub fn handle_key_event(&mut self, _key: KeyEvent) -> Option { + pub fn handle_key_event(&self, _key: KeyEvent) -> Option { Some(Action::CancelCurrentPopup) } diff --git a/src/tui/help.rs b/src/tui/help.rs index 900a10bc..4150aee7 100644 --- a/src/tui/help.rs +++ b/src/tui/help.rs @@ -15,16 +15,14 @@ use ratatui::{style::Styled, text::Span}; pub fn cli_flag<'a, T>(f: T) -> Span<'a> where - T: Into>, - T: Styled>, + T: Into> + Styled>, { f.set_style(THEME.cli_flag) } pub fn help_key<'a, T>(k: T) -> Span<'a> where - T: Into>, - T: Styled>, + T: Into> + Styled>, { let mut key_string = String::from("\u{00a0}"); key_string.push_str(&k.into()); @@ -33,8 +31,7 @@ where } pub fn help_desc<'a, T>(d: T) -> Span<'a> where - T: Into>, - T: Styled>, + T: Into> + Styled>, { let mut desc_string = String::from("\u{00a0}"); desc_string.push_str(&d.into()); @@ -44,8 +41,7 @@ where pub fn fancy_help_desc<'a, T>(d: T) -> Span<'a> where - T: Into>, - T: Styled>, + T: Into> + Styled>, { let mut desc_string = String::from("\u{00a0}"); desc_string.push_str(&d.into()); diff --git a/src/tui/hit_manager.rs b/src/tui/hit_manager.rs index 1dd5f8ed..c386af27 100644 --- a/src/tui/hit_manager.rs +++ b/src/tui/hit_manager.rs @@ -53,11 +53,10 @@ impl BreakPointHitEntry { THEME.hit_entry_plain_text, ), Span::raw("("), - if let Some(pattern) = &self.breakpoint_pattern { - Span::styled(pattern.clone(), THEME.hit_entry_breakpoint_pattern) - } else { - Span::styled("deleted", THEME.hit_entry_no_breakpoint_pattern) - }, + self.breakpoint_pattern.as_ref().map_or_else( + || Span::styled("deleted", THEME.hit_entry_no_breakpoint_pattern), + |pattern| Span::styled(pattern.clone(), THEME.hit_entry_breakpoint_pattern), + ), Span::raw(")"), space.clone(), Span::styled("at", THEME.hit_entry_plain_text), diff --git a/src/tui/partial_line.rs b/src/tui/partial_line.rs index 6373049a..a46acb81 100644 --- a/src/tui/partial_line.rs +++ b/src/tui/partial_line.rs @@ -10,7 +10,7 @@ pub trait PartialLine<'a> { impl<'a> PartialLine<'a> for Line<'a> { // Unicode is hard - fn substring(mut self, start: usize, len: u16) -> Line<'a> { + fn substring(mut self, start: usize, len: u16) -> Self { let len = len as usize; let end = start + len; let end = if end > self.width() { diff --git a/src/tui/pseudo_term.rs b/src/tui/pseudo_term.rs index 71034928..d4c232de 100644 --- a/src/tui/pseudo_term.rs +++ b/src/tui/pseudo_term.rs @@ -76,8 +76,7 @@ impl PseudoTerminalPane { } if size > 0 { processed_buf.extend_from_slice(&buf[..size]); - let mut parser = parser.write().unwrap(); - parser.process(&processed_buf); + parser.write().unwrap().process(&processed_buf); // Clear the processed portion of the buffer processed_buf.clear(); @@ -196,8 +195,7 @@ impl PseudoTerminalPane { return Ok(()); } self.size = size; - let mut parser = self.parser.write().unwrap(); - parser.set_size(size.rows, size.cols); + self.parser.write().unwrap().set_size(size.rows, size.cols); self.pty_master.resize(size)?; Ok(()) }