use std::collections::HashMap;
use std::os::fd::RawFd;
use wireshift_core::{Error, Result};
pub fn duplicate_fd(fds: &[RawFd]) -> Option<RawFd> {
let mut seen = std::collections::HashSet::with_capacity(fds.len());
fds.iter().find(|&&fd| !seen.insert(fd)).copied()
}
#[derive(Debug, Default)]
pub struct FileRegistryTable {
pub(crate) slots_by_fd: HashMap<RawFd, u32>,
}
impl FileRegistryTable {
pub fn register(&mut self, submitter: &io_uring::Submitter<'_>, fds: &[RawFd]) -> Result<()> {
if let Some(duplicate) = duplicate_fd(fds) {
return Err(Error::validation(
format!("duplicate fd {duplicate} cannot be mapped to multiple fixed-file slots"),
"register each fd at most once or duplicate the descriptor before registering",
));
}
submitter.register_files(fds).map_err(|error| {
Error::io(
"IORING_REGISTER_FILES failed",
error,
"ensure every fd is valid and the kernel supports fixed-file registration",
)
})?;
self.slots_by_fd = fds
.iter()
.enumerate()
.map(|(slot, &fd)| (fd, slot as u32))
.collect();
Ok(())
}
pub fn unregister(&mut self, submitter: &io_uring::Submitter<'_>) -> Result<()> {
submitter.unregister_files().map_err(|error| {
Error::io(
"IORING_UNREGISTER_FILES failed",
error,
"wait for in-flight fixed-file requests to finish before unregistering files",
)
})?;
self.slots_by_fd.clear();
Ok(())
}
pub fn lookup(&self, fd: RawFd) -> Option<u32> {
self.slots_by_fd.get(&fd).copied()
}
pub fn clear(&mut self) {
self.slots_by_fd.clear();
}
}