From ce1b4011d409997b10ca205f459cedcb6b292bd7 Mon Sep 17 00:00:00 2001 From: salmon Date: Sun, 9 Aug 2026 23:53:47 +0200 Subject: Make daemon socket/PID paths environment-independent; fix rc service HOME --- src/config.rs | 38 ++++++++++++++++++++++++++++++++++---- src/daemon.rs | 14 +++----------- 2 files changed, 37 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/config.rs b/src/config.rs index 67cb366..f20fb3a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -303,9 +303,39 @@ impl Config { } pub fn get_socket_path() -> PathBuf { - let runtime_dir = std::env::var("XDG_RUNTIME_DIR") - .map(PathBuf::from) - .unwrap_or_else(|_| PathBuf::from("/tmp")); - runtime_dir.join("rsplayer").join("daemon.sock") + runtime_dir().join("daemon.sock") } } + +/// Directory holding the daemon socket and PID file. +/// +/// Uses the user's XDG state directory (~/.local/state/rsplayer) so the path +/// is identical no matter how the daemon was started (rc.d service, login +/// shell, ...). The previous XDG_RUNTIME_DIR-based path depended on the +/// environment and broke the service/CLI handshake on FreeBSD, where +/// XDG_RUNTIME_DIR is often unset (falling back to the world-writable +/// /tmp/rsplayer). +pub fn runtime_dir() -> PathBuf { + if let Some(base) = directories::BaseDirs::new() + && let Some(state) = base.state_dir() + { + return state.join("rsplayer"); + } + // Fallback when no home/state dir is resolvable + std::env::var("XDG_RUNTIME_DIR") + .map(PathBuf::from) + .unwrap_or_else(|_| PathBuf::from("/tmp")) + .join("rsplayer") +} + +/// Create the runtime directory (private, 0700) and return its path. +pub fn ensure_runtime_dir() -> std::io::Result { + let dir = runtime_dir(); + std::fs::create_dir_all(&dir)?; + #[cfg(unix)] + { + use std::os::unix::fs::PermissionsExt; + std::fs::set_permissions(&dir, std::fs::Permissions::from_mode(0o700))?; + } + Ok(dir) +} diff --git a/src/daemon.rs b/src/daemon.rs index 279620d..21f1a3b 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -203,13 +203,8 @@ pub fn start_daemon() -> Result<(), Box> { std::fs::remove_file(&socket_path).ok(); } - // Create runtime directory - if let Some(parent) = socket_path.parent() { - std::fs::create_dir_all(parent)?; - } - if let Some(parent) = pid_path.parent() { - std::fs::create_dir_all(parent)?; - } + // Create runtime directory (private, 0700) + crate::config::ensure_runtime_dir()?; // Write PID file let pid = std::process::id(); @@ -1609,10 +1604,7 @@ fn find_audio_in_dir(dir: &Path) -> Option> { /// Get the PID file path for the daemon fn get_pid_path(_config: &Config) -> std::path::PathBuf { - let runtime_dir = std::env::var("XDG_RUNTIME_DIR") - .map(std::path::PathBuf::from) - .unwrap_or_else(|_| std::path::PathBuf::from("/tmp")); - runtime_dir.join("rsplayer").join("rsplayer.pid") + crate::config::runtime_dir().join("rsplayer.pid") } /// Check if a process with the given PID is running -- cgit v1.2.3