use std::fs::{File, OpenOptions};
use std::os::fd::AsFd;
use std::path::PathBuf;
use color_eyre::eyre::{Result, WrapErr, eyre};
use rustix::fs::{FlockOperation, flock};
pub struct Lock {
_file: File,
}
impl Lock {
pub fn acquire() -> Result<Self> {
let path = lock_path();
let file = OpenOptions::new()
.write(true)
.create(true)
.truncate(false)
.mode(0o600)
.open(&path)
.wrap_err_with(|| format!("open lock file {}", path.display()))?;
match flock(file.as_fd(), FlockOperation::NonBlockingLockExclusive) {
Ok(()) => Ok(Self { _file: file }),
Err(rustix::io::Errno::WOULDBLOCK) => Err(eyre!(
"another sip instance is already running for this Wayland session"
)),
Err(e) => Err(e).wrap_err("acquire session lock"),
}
}
}
fn lock_path() -> PathBuf {
let runtime = std::env::var_os("XDG_RUNTIME_DIR")
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from("/tmp"));
let display = std::env::var("WAYLAND_DISPLAY").unwrap_or_else(|_| "wayland-0".into());
runtime.join(format!("sip-{display}.lock"))
}
use std::os::unix::fs::OpenOptionsExt as _;