From ce51c40d0daa24d8fc31d0b572a7e8aa78f11d7c Mon Sep 17 00:00:00 2001 From: Thomas Eizinger Date: Tue, 6 May 2025 08:45:53 +1000 Subject: [PATCH] refactor(rust): move `known_dirs` to `bin-shared` (#9026) The `known_dirs` module is used across the headless-client and the GUI client. It should live in `bin-shared` where all the other cross-platform modules are. --------- Signed-off-by: Thomas Eizinger --- rust/Cargo.lock | 2 +- rust/bin-shared/Cargo.toml | 1 + .../src/known_dirs.rs | 0 .../src/known_dirs/linux.rs | 2 +- .../src/known_dirs/macos.rs | 0 .../src/known_dirs/windows.rs | 15 ++++++++++++++- rust/bin-shared/src/lib.rs | 1 + .../bin-shared/src/tun_device_manager/windows.rs | 2 +- rust/bin-shared/src/windows.rs | 16 +--------------- rust/gui-client/src-common/src/auth.rs | 2 +- .../src-common/src/controller/ran_before.rs | 2 +- .../gui-client/src-common/src/deep_link/linux.rs | 2 +- rust/gui-client/src-common/src/logging.rs | 2 +- rust/gui-client/src-common/src/settings.rs | 2 +- rust/gui-client/src-common/src/updates.rs | 2 +- rust/headless-client/Cargo.toml | 1 - rust/headless-client/src/device_id.rs | 2 +- rust/headless-client/src/ipc_service.rs | 8 ++++---- .../headless-client/src/ipc_service/ipc/linux.rs | 2 +- rust/headless-client/src/lib.rs | 5 ++--- 20 files changed, 34 insertions(+), 35 deletions(-) rename rust/{headless-client => bin-shared}/src/known_dirs.rs (100%) rename rust/{headless-client => bin-shared}/src/known_dirs/linux.rs (98%) rename rust/{headless-client => bin-shared}/src/known_dirs/macos.rs (100%) rename rust/{headless-client => bin-shared}/src/known_dirs/windows.rs (73%) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index bd45b9b7a..7e4b2aeb7 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -2097,6 +2097,7 @@ dependencies = [ "bufferpool", "bytes", "clap", + "dirs 5.0.1", "firezone-logging", "flume", "futures", @@ -2272,7 +2273,6 @@ dependencies = [ "clap", "connlib-client-shared", "connlib-model", - "dirs 5.0.1", "dns-types", "firezone-bin-shared", "firezone-logging", diff --git a/rust/bin-shared/Cargo.toml b/rust/bin-shared/Cargo.toml index c22d61042..8355fe603 100644 --- a/rust/bin-shared/Cargo.toml +++ b/rust/bin-shared/Cargo.toml @@ -28,6 +28,7 @@ bytes = { workspace = true } tokio = { workspace = true, features = ["macros", "rt-multi-thread"] } [target.'cfg(target_os = "linux")'.dependencies] +dirs = { workspace = true } flume = { workspace = true } libc = { workspace = true } netlink-packet-core = { version = "0.7" } diff --git a/rust/headless-client/src/known_dirs.rs b/rust/bin-shared/src/known_dirs.rs similarity index 100% rename from rust/headless-client/src/known_dirs.rs rename to rust/bin-shared/src/known_dirs.rs diff --git a/rust/headless-client/src/known_dirs/linux.rs b/rust/bin-shared/src/known_dirs/linux.rs similarity index 98% rename from rust/headless-client/src/known_dirs/linux.rs rename to rust/bin-shared/src/known_dirs/linux.rs index c2a2dd88b..c773bcee9 100644 --- a/rust/headless-client/src/known_dirs/linux.rs +++ b/rust/bin-shared/src/known_dirs/linux.rs @@ -1,4 +1,4 @@ -use firezone_bin_shared::BUNDLE_ID; +use crate::BUNDLE_ID; use std::path::PathBuf; /// Path for IPC service config that the IPC service can write diff --git a/rust/headless-client/src/known_dirs/macos.rs b/rust/bin-shared/src/known_dirs/macos.rs similarity index 100% rename from rust/headless-client/src/known_dirs/macos.rs rename to rust/bin-shared/src/known_dirs/macos.rs diff --git a/rust/headless-client/src/known_dirs/windows.rs b/rust/bin-shared/src/known_dirs/windows.rs similarity index 73% rename from rust/headless-client/src/known_dirs/windows.rs rename to rust/bin-shared/src/known_dirs/windows.rs index a474631b9..fa29bbb33 100644 --- a/rust/headless-client/src/known_dirs/windows.rs +++ b/rust/bin-shared/src/known_dirs/windows.rs @@ -1,7 +1,20 @@ -use firezone_bin_shared::{BUNDLE_ID, platform::app_local_data_dir}; +use crate::BUNDLE_ID; +use anyhow::{Context as _, Result}; use known_folders::{KnownFolder, get_known_folder_path}; use std::path::PathBuf; +/// Returns e.g. `C:/Users/User/AppData/Local/dev.firezone.client +/// +/// This is where we can save config, logs, crash dumps, etc. +/// It's per-user and doesn't roam across different PCs in the same domain. +/// It's read-write for non-elevated processes. +pub fn app_local_data_dir() -> Result { + let path = get_known_folder_path(KnownFolder::LocalAppData) + .context("Can't find %LOCALAPPDATA% dir")? + .join(crate::BUNDLE_ID); + Ok(path) +} + /// Path for IPC service config that the IPC service can write /// /// All writes should use `atomicwrites`. diff --git a/rust/bin-shared/src/lib.rs b/rust/bin-shared/src/lib.rs index e5d7b829e..89c88c93d 100644 --- a/rust/bin-shared/src/lib.rs +++ b/rust/bin-shared/src/lib.rs @@ -23,6 +23,7 @@ pub mod macos; #[cfg(target_os = "macos")] pub use macos as platform; +pub mod known_dirs; pub mod uptime; pub const TOKEN_ENV_KEY: &str = "FIREZONE_TOKEN"; diff --git a/rust/bin-shared/src/tun_device_manager/windows.rs b/rust/bin-shared/src/tun_device_manager/windows.rs index 0abc30d86..24b50aa83 100644 --- a/rust/bin-shared/src/tun_device_manager/windows.rs +++ b/rust/bin-shared/src/tun_device_manager/windows.rs @@ -630,7 +630,7 @@ fn file_length(f: &std::fs::File) -> Result { /// /// e.g. `C:\Users\User\AppData\Local\dev.firezone.client\data\wintun.dll` fn wintun_dll_path() -> Result { - let path = crate::windows::app_local_data_dir()? + let path = crate::known_dirs::platform::app_local_data_dir()? .join("data") .join("wintun.dll"); Ok(path) diff --git a/rust/bin-shared/src/windows.rs b/rust/bin-shared/src/windows.rs index ec35f9742..c520b6c88 100644 --- a/rust/bin-shared/src/windows.rs +++ b/rust/bin-shared/src/windows.rs @@ -1,14 +1,12 @@ use crate::TUNNEL_NAME; -use anyhow::{Context as _, Result}; +use anyhow::Result; use firezone_logging::err_with_src; -use known_folders::{KnownFolder, get_known_folder_path}; use socket_factory::{TcpSocket, UdpSocket}; use std::{ cmp::Ordering, io, mem::MaybeUninit, net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}, - path::PathBuf, ptr::null, }; use uuid::Uuid; @@ -106,18 +104,6 @@ impl Default for DnsControlMethod { } } -/// Returns e.g. `C:/Users/User/AppData/Local/dev.firezone.client -/// -/// This is where we can save config, logs, crash dumps, etc. -/// It's per-user and doesn't roam across different PCs in the same domain. -/// It's read-write for non-elevated processes. -pub fn app_local_data_dir() -> Result { - let path = get_known_folder_path(KnownFolder::LocalAppData) - .context("Can't find %LOCALAPPDATA% dir")? - .join(crate::BUNDLE_ID); - Ok(path) -} - pub fn tcp_socket_factory(addr: &SocketAddr) -> io::Result { delete_all_routing_entries_matching(addr.ip())?; diff --git a/rust/gui-client/src-common/src/auth.rs b/rust/gui-client/src-common/src/auth.rs index bb27f0f86..0a668ea20 100644 --- a/rust/gui-client/src-common/src/auth.rs +++ b/rust/gui-client/src-common/src/auth.rs @@ -1,7 +1,7 @@ //! Fulfills use anyhow::{Context, Result}; -use firezone_headless_client::known_dirs; +use firezone_bin_shared::known_dirs; use firezone_logging::err_with_src; use rand::{RngCore, thread_rng}; use secrecy::{ExposeSecret, SecretString}; diff --git a/rust/gui-client/src-common/src/controller/ran_before.rs b/rust/gui-client/src-common/src/controller/ran_before.rs index 8baa5d8f9..6d7d094d9 100644 --- a/rust/gui-client/src-common/src/controller/ran_before.rs +++ b/rust/gui-client/src-common/src/controller/ran_before.rs @@ -26,6 +26,6 @@ pub(crate) async fn set() -> Result<()> { fn path() -> Result { let session_dir = - firezone_headless_client::known_dirs::session().context("Couldn't find session dir")?; + firezone_bin_shared::known_dirs::session().context("Couldn't find session dir")?; Ok(session_dir.join("ran_before.txt")) } diff --git a/rust/gui-client/src-common/src/deep_link/linux.rs b/rust/gui-client/src-common/src/deep_link/linux.rs index e31695b97..940dfaf4f 100644 --- a/rust/gui-client/src-common/src/deep_link/linux.rs +++ b/rust/gui-client/src-common/src/deep_link/linux.rs @@ -1,5 +1,5 @@ use anyhow::{Context, Result, bail}; -use firezone_headless_client::known_dirs; +use firezone_bin_shared::known_dirs; use secrecy::{ExposeSecret, Secret}; use std::{io::ErrorKind, path::PathBuf, process::Command}; use tokio::{ diff --git a/rust/gui-client/src-common/src/logging.rs b/rust/gui-client/src-common/src/logging.rs index d4bcb781a..ce0b728a8 100644 --- a/rust/gui-client/src-common/src/logging.rs +++ b/rust/gui-client/src-common/src/logging.rs @@ -1,7 +1,7 @@ //! Everything for logging to files, zipping up the files for export, and counting the files use anyhow::{Context as _, Result, bail}; -use firezone_headless_client::known_dirs; +use firezone_bin_shared::known_dirs; use serde::Serialize; use std::{ fs, diff --git a/rust/gui-client/src-common/src/settings.rs b/rust/gui-client/src-common/src/settings.rs index 924daed28..e30b5024d 100644 --- a/rust/gui-client/src-common/src/settings.rs +++ b/rust/gui-client/src-common/src/settings.rs @@ -3,7 +3,7 @@ use anyhow::{Context as _, Result}; use connlib_model::ResourceId; -use firezone_headless_client::known_dirs; +use firezone_bin_shared::known_dirs; use serde::{Deserialize, Serialize}; use std::{collections::HashSet, path::PathBuf}; use url::Url; diff --git a/rust/gui-client/src-common/src/updates.rs b/rust/gui-client/src-common/src/updates.rs index ffbd33b51..2e154d57f 100644 --- a/rust/gui-client/src-common/src/updates.rs +++ b/rust/gui-client/src-common/src/updates.rs @@ -205,7 +205,7 @@ impl Checker { } fn version_file_path() -> Result { - Ok(firezone_headless_client::known_dirs::session() + Ok(firezone_bin_shared::known_dirs::session() .context("Couldn't find session dir")? .join("latest_version_seen.txt")) } diff --git a/rust/headless-client/Cargo.toml b/rust/headless-client/Cargo.toml index a4b654da4..4457186b0 100644 --- a/rust/headless-client/Cargo.toml +++ b/rust/headless-client/Cargo.toml @@ -51,7 +51,6 @@ tempfile = { workspace = true } mutants = "0.0.3" # Needed to mark functions as exempt from `cargo-mutants` testing [target.'cfg(target_os = "linux")'.dependencies] -dirs = { workspace = true } libc = { workspace = true } nix = { workspace = true, features = ["fs", "user", "socket"] } resolv-conf = { workspace = true } diff --git a/rust/headless-client/src/device_id.rs b/rust/headless-client/src/device_id.rs index ff1851cc4..31d732b3e 100644 --- a/rust/headless-client/src/device_id.rs +++ b/rust/headless-client/src/device_id.rs @@ -15,7 +15,7 @@ pub struct DeviceId { /// e.g. `C:\ProgramData\dev.firezone.client/firezone-id.json` or /// `/var/lib/dev.firezone.client/config/firezone-id.json`. pub(crate) fn path() -> Result { - let path = crate::known_dirs::ipc_service_config() + let path = firezone_bin_shared::known_dirs::ipc_service_config() .context("Failed to compute path for firezone-id file")? .join("firezone-id.json"); Ok(path) diff --git a/rust/headless-client/src/ipc_service.rs b/rust/headless-client/src/ipc_service.rs index ed9f1e9bf..fe24ba843 100644 --- a/rust/headless-client/src/ipc_service.rs +++ b/rust/headless-client/src/ipc_service.rs @@ -1,13 +1,12 @@ use crate::{ - CallbackHandler, CliCommon, ConnlibMsg, device_id, dns_control::DnsController, known_dirs, - signals, + CallbackHandler, CliCommon, ConnlibMsg, device_id, dns_control::DnsController, signals, }; use anyhow::{Context as _, Result, bail}; use atomicwrites::{AtomicFile, OverwriteBehavior}; use clap::Parser; use connlib_model::ResourceView; use firezone_bin_shared::{ - TOKEN_ENV_KEY, TunDeviceManager, + TOKEN_ENV_KEY, TunDeviceManager, known_dirs, platform::{DnsControlMethod, tcp_socket_factory, udp_socket_factory}, }; use firezone_logging::{FilterReloadHandle, err_with_src, sentry_layer, telemetry_span}; @@ -472,7 +471,8 @@ impl<'a> Handler<'a> { match msg { ClientMsg::ClearLogs => { let result = crate::clear_logs( - &crate::known_dirs::ipc_service_logs().context("Can't compute logs dir")?, + &firezone_bin_shared::known_dirs::ipc_service_logs() + .context("Can't compute logs dir")?, ) .await; self.send_ipc(ServerMsg::ClearedLogs(result.map_err(|e| e.to_string()))) diff --git a/rust/headless-client/src/ipc_service/ipc/linux.rs b/rust/headless-client/src/ipc_service/ipc/linux.rs index d1f76d635..6cda463af 100644 --- a/rust/headless-client/src/ipc_service/ipc/linux.rs +++ b/rust/headless-client/src/ipc_service/ipc/linux.rs @@ -87,7 +87,7 @@ impl Server { fn ipc_path(id: ServiceId) -> PathBuf { match id { ServiceId::Prod => PathBuf::from("/run").join(BUNDLE_ID).join("ipc.sock"), - ServiceId::Test(id) => crate::known_dirs::runtime() + ServiceId::Test(id) => firezone_bin_shared::known_dirs::runtime() .expect("`known_dirs::runtime()` should always work") .join(format!("ipc_test_{id}.sock")), } diff --git a/rust/headless-client/src/lib.rs b/rust/headless-client/src/lib.rs index b01b53482..13befd5f2 100644 --- a/rust/headless-client/src/lib.rs +++ b/rust/headless-client/src/lib.rs @@ -29,7 +29,6 @@ pub mod device_id; // Pub because the GUI reads the system resolvers pub mod dns_control; mod ipc_service; -pub mod known_dirs; // TODO: Move to `bin-shared`? pub mod signals; @@ -170,8 +169,8 @@ pub(crate) fn get_log_filter() -> Result { return Ok(filter); } - if let Ok(filter) = - std::fs::read_to_string(known_dirs::ipc_log_filter()?).map(|s| s.trim().to_string()) + if let Ok(filter) = std::fs::read_to_string(firezone_bin_shared::known_dirs::ipc_log_filter()?) + .map(|s| s.trim().to_string()) { return Ok(filter); }