use std::io;
use std::path::Path;
use std::time::Duration;
pub(crate) const PROBE_TIMEOUT: Duration = Duration::from_millis(50);
#[inline]
pub(crate) fn is_abstract_path(path: &Path) -> bool {
path.to_str().is_some_and(|s| s.starts_with('@'))
}
pub(crate) fn bind_abstract(path: &Path) -> io::Result<std::os::unix::net::UnixListener> {
#[cfg(target_os = "linux")]
{
use std::os::linux::net::SocketAddrExt;
let name = &path.to_str().unwrap().as_bytes()[1..];
let addr = std::os::unix::net::SocketAddr::from_abstract_name(name)?;
let listener = std::os::unix::net::UnixListener::bind_addr(&addr)?;
listener.set_nonblocking(true)?;
Ok(listener)
}
#[cfg(not(target_os = "linux"))]
{
let _ = path;
Err(io::Error::new(
io::ErrorKind::Unsupported,
"abstract Unix socket paths (`@`-prefixed) are Linux-only",
))
}
}
pub(crate) fn existing_socket(path: &Path) -> io::Result<bool> {
use std::os::unix::fs::FileTypeExt;
let meta = match std::fs::symlink_metadata(path) {
Ok(m) => m,
Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(false),
Err(e) => return Err(e),
};
if !meta.file_type().is_socket() {
return Err(io::Error::new(
io::ErrorKind::AlreadyExists,
format!(
"{} exists but is not a unix socket; refusing to remove",
path.display()
),
));
}
Ok(true)
}
pub(crate) fn in_use(path: &Path) -> io::Error {
io::Error::new(
io::ErrorKind::AddrInUse,
format!("Unix socket {} is already in use", path.display()),
)
}
pub(crate) fn remove_stale(path: &Path) -> io::Result<()> {
match std::fs::remove_file(path) {
Ok(()) => Ok(()),
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(e),
}
}