use std::path::PathBuf;
#[cfg(target_os = "macos")]
#[derive(Debug)]
#[allow(dead_code)]
pub(super) struct WrapperSingleInstanceLock {
_file: std::fs::File,
}
#[allow(dead_code)]
pub(super) fn wrapper_lock_path() -> Option<PathBuf> {
dirs::cache_dir().map(|d| d.join("Freenet").join("wrapper.lock"))
}
#[derive(Debug)]
#[allow(dead_code)]
pub(super) enum AcquireWrapperLockOutcome {
Acquired(WrapperSingleInstanceLock),
AnotherWrapperRunning,
UnavailableSoProceed,
}
#[cfg(target_os = "macos")]
#[allow(dead_code)]
pub(super) fn acquire_wrapper_single_instance_lock() -> AcquireWrapperLockOutcome {
use std::os::unix::io::AsRawFd;
let Some(lock_path) = wrapper_lock_path() else {
tracing::warn!("Wrapper lock: cache directory unresolvable; proceeding without lock");
return AcquireWrapperLockOutcome::UnavailableSoProceed;
};
if let Some(parent) = lock_path.parent() {
if let Err(e) = std::fs::create_dir_all(parent) {
tracing::warn!(
"Wrapper lock: failed to create {}: {}; proceeding without lock",
parent.display(),
e
);
return AcquireWrapperLockOutcome::UnavailableSoProceed;
}
}
let file = match std::fs::OpenOptions::new()
.create(true)
.truncate(false)
.write(true)
.open(&lock_path)
{
Ok(f) => f,
Err(e) => {
tracing::warn!(
"Wrapper lock: failed to open {}: {}; proceeding without lock",
lock_path.display(),
e
);
return AcquireWrapperLockOutcome::UnavailableSoProceed;
}
};
let rc = unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) };
if rc != 0 {
AcquireWrapperLockOutcome::AnotherWrapperRunning
} else {
AcquireWrapperLockOutcome::Acquired(WrapperSingleInstanceLock { _file: file })
}
}
#[cfg(not(target_os = "macos"))]
#[allow(dead_code)]
pub(super) fn acquire_wrapper_single_instance_lock() -> AcquireWrapperLockOutcome {
AcquireWrapperLockOutcome::UnavailableSoProceed
}
#[cfg(not(target_os = "macos"))]
#[derive(Debug)]
#[allow(dead_code)]
pub(super) struct WrapperSingleInstanceLock;
#[cfg(any(target_os = "windows", target_os = "macos"))]
pub(super) static FIRST_RUN_OPENER_SPAWNED: std::sync::atomic::AtomicBool =
std::sync::atomic::AtomicBool::new(false);