use crate::error::LuminationError;
use glob::glob;
use std::{fs::read_link, path::PathBuf};
use tracing::{Level, event};
#[derive(Debug)]
pub(crate) struct ProcInfo {
pub(crate) socket: String,
pub(crate) pid: u32,
pub(crate) name: String,
pub(crate) _path: String,
}
pub(crate) fn proc_with_sockets() -> Result<Vec<ProcInfo>, LuminationError> {
let glob_path = "/proc/*/fd/*";
let paths = match glob(glob_path) {
Ok(result) => result,
Err(err) => {
event!(
Level::ERROR,
"[lumination] Failed to glob proc ids: {err:?}"
);
return Err(LuminationError::Procs);
}
};
let mut info = Vec::new();
for path_result in paths {
if path_result.is_err() {
continue;
}
let mut path = path_result.unwrap_or_default();
let link = match read_link(&path) {
Ok(result) => result,
Err(_err) => continue,
};
if link.to_str().is_some_and(|x| x.contains("socket")) {
path.pop();
path.pop();
let pid = path
.file_name()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_string();
path.push("exe");
let name = match read_link(&path) {
Ok(result) => result,
Err(_err) => PathBuf::new(),
};
let proc = ProcInfo {
socket: link.to_str().unwrap_or_default().to_string(),
pid: pid.parse::<u32>().unwrap_or_default(),
_path: name.to_str().unwrap_or_default().to_string(),
name: name
.file_name()
.unwrap_or_default()
.to_str()
.unwrap_or_default()
.to_string(),
};
info.push(proc);
}
}
Ok(info)
}
#[cfg(test)]
mod tests {
use super::proc_with_sockets;
#[test]
fn test_proc_with_sockets() {
let results = proc_with_sockets().unwrap();
assert!(results.len() > 2);
}
}