From d608ffeeda1a479c9dc0e5f6ad269ba07a510d7f Mon Sep 17 00:00:00 2001 From: Andrew Guschin Date: Fri, 30 Oct 2026 03:10:41 +0400 Subject: Implement Linux proxy controller, subscription state, and CLI/TUI --- src/locking.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/locking.rs (limited to 'src/locking.rs') diff --git a/src/locking.rs b/src/locking.rs new file mode 100644 index 0000000..1c39471 --- /dev/null +++ b/src/locking.rs @@ -0,0 +1,35 @@ +use anyhow::{Context, Result, ensure}; +use std::{ + fs::{File, OpenOptions}, + os::fd::AsRawFd, + os::unix::fs::{MetadataExt, OpenOptionsExt}, + path::Path, +}; + +pub fn controller_lock() -> Result { + let directory = Path::new("/run/roentgen"); + std::fs::create_dir_all(directory)?; + let metadata = std::fs::symlink_metadata(directory)?; + ensure!( + metadata.is_dir() + && metadata.uid() == unsafe { libc::geteuid() } + && metadata.mode() & 0o022 == 0, + "Runtime directory must be service-owned and not writable by other users" + ); + let file = OpenOptions::new() + .create(true) + .truncate(false) + .read(true) + .write(true) + .mode(0o600) + .custom_flags(libc::O_NOFOLLOW) + .open(directory.join("controller.lock")) + .context("Open controller lock")?; + // SAFETY: file owns this live fd; flock does not retain a pointer. + let result = unsafe { libc::flock(file.as_raw_fd(), libc::LOCK_EX | libc::LOCK_NB) }; + ensure!( + result == 0, + "Another controller is running; stop it before explicit recovery" + ); + Ok(file) +} -- cgit v1.2.3