From 905353c61f97722dc4a07c8ec850e26757af1c43 Mon Sep 17 00:00:00 2001 From: Thomas Frans Date: Thu, 12 Oct 2023 23:53:20 +0200 Subject: [PATCH] fix!: create IPC socket in user runtime directory Each user has their own runtime directory at `/run/user/`. Creating the IPC socket in there makes sure it is cleaned up regardless of whether `ncspot` exits normally. BREAKING CHANGE: move IPC socket location --- src/application.rs | 6 ++++-- src/utils.rs | 46 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/application.rs b/src/application.rs index 9e016a52..4002a911 100644 --- a/src/application.rs +++ b/src/application.rs @@ -21,7 +21,7 @@ use crate::library::Library; use crate::queue::Queue; use crate::spotify::{PlayerEvent, Spotify}; use crate::ui::create_cursive; -use crate::{authentication, ui}; +use crate::{authentication, ui, utils}; use crate::{command, queue, spotify}; #[cfg(feature = "mpris")] @@ -165,7 +165,9 @@ impl Application { #[cfg(unix)] let ipc = ipc::IpcSocket::new( ASYNC_RUNTIME.get().unwrap().handle(), - crate::config::cache_path("ncspot.sock"), + utils::create_runtime_directory() + .unwrap() + .join("ncspot.sock"), event_manager.clone(), ) .map_err(|e| e.to_string())?; diff --git a/src/utils.rs b/src/utils.rs index e4ae725b..bd3cddb1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::fmt::Write; +use std::{fmt::Write, path::PathBuf}; /// Returns a human readable String of a Duration /// @@ -59,3 +59,47 @@ pub fn download(url: String, path: std::path::PathBuf) -> Result<(), std::io::Er std::io::copy(&mut resp, &mut file)?; Ok(()) } + +/// Create the application specific runtime directory and return the path to it. +/// +/// If the directory already exists and has the correct permissions, this function just returns the +/// existing directory. The contents stored in this directory are not necessarily persisted across +/// reboots. Stored files should be small since they could reside in memory (like on a tmpfs mount). +#[cfg(unix)] +pub fn create_runtime_directory() -> Result> { + use std::fs; + + let linux_runtime_directory = + PathBuf::from(format!("/run/user/{}/", unsafe { libc::getuid() })); + let unix_runtime_directory = PathBuf::from("/tmp/"); + + let user_runtime_directory = if let Some(xdg_runtime_directory) = xdg_runtime_directory() { + Some(xdg_runtime_directory.join("ncspot")) + } else if cfg!(linux) && linux_runtime_directory.exists() { + Some(linux_runtime_directory.join("ncspot")) + } else if unix_runtime_directory.exists() { + Some(unix_runtime_directory.join(format!("ncspot-{}", unsafe { libc::getuid() }))) + } else { + None + } + .ok_or("no runtime directory found")?; + + let creation_result = fs::create_dir(&user_runtime_directory); + + if creation_result.is_ok() + || matches!( + creation_result.as_ref().unwrap_err().kind(), + std::io::ErrorKind::AlreadyExists + ) + { + Ok(user_runtime_directory) + } else { + #[allow(clippy::unnecessary_unwrap)] + Err(Box::new(creation_result.unwrap_err())) + } +} + +#[cfg(unix)] +fn xdg_runtime_directory() -> Option { + std::env::var("XDG_RUNTIME_DIR").ok().map(Into::into) +}