From cf0e3ef15b83f4566877c90d89640c1d35c7bbae Mon Sep 17 00:00:00 2001 From: timvisee Date: Wed, 24 Nov 2021 13:53:38 +0100 Subject: [PATCH] Make server directory relative to configuration file directory --- src/action/start.rs | 4 ++-- src/config.rs | 36 +++++++++++++++++++++++++++++++----- src/mc/server_properties.rs | 14 +++++++------- src/server.rs | 4 ++-- src/service/ban_reload.rs | 4 ++-- src/status.rs | 4 ++-- 6 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/action/start.rs b/src/action/start.rs index 77205f0..aa9326a 100644 --- a/src/action/start.rs +++ b/src/action/start.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use clap::ArgMatches; -use crate::config::{self, Config}; +use crate::config::{self, Config, Server as ConfigServer}; use crate::mc::server_properties; use crate::proto; use crate::service; @@ -120,7 +120,7 @@ fn rewrite_server_properties(config: &Config) { } // Ensure server directory is set, it must exist - let dir = match &config.server.directory { + let dir = match ConfigServer::server_directory(config) { Some(dir) => dir, None => { warn!(target: "lazymc", "Not rewriting {} file, server directory not configured (server.directory)", server_properties::FILE); diff --git a/src/config.rs b/src/config.rs index 6291022..0c8a5d7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,7 +1,7 @@ use std::fs; use std::io; use std::net::SocketAddr; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use clap::ArgMatches; use serde::Deserialize; @@ -63,6 +63,12 @@ pub fn load(matches: &ArgMatches) -> Config { /// Configuration. #[derive(Debug, Deserialize)] pub struct Config { + /// Configuration path if known. + /// + /// Should be used as base directory for filesystem operations. + #[serde(skip)] + pub path: Option, + /// Public configuration. #[serde(default)] pub public: Public, @@ -101,9 +107,9 @@ pub struct Config { impl Config { /// Load configuration from file. - pub fn load>(path: P) -> Result { - let data = fs::read(path)?; - let config: Config = toml::from_slice(&data)?; + pub fn load(path: PathBuf) -> Result { + let data = fs::read(&path)?; + let mut config: Config = toml::from_slice(&data)?; // Show warning if config version is problematic match &config.config.version { @@ -118,6 +124,7 @@ impl Config { Ok(true) => {} }, } + config.path.replace(path); Ok(config) } @@ -152,8 +159,10 @@ impl Default for Public { #[derive(Debug, Deserialize)] pub struct Server { /// Server directory. + /// + /// Private because you should use `Server::server_directory()` instead. #[serde(default = "option_pathbuf_dot")] - pub directory: Option, + directory: Option, /// Start command. pub command: String, @@ -194,6 +203,23 @@ pub struct Server { pub send_proxy_v2: bool, } +impl Server { + /// Get the server directory. + /// + /// This does not check whether it exists. + pub fn server_directory(config: &Config) -> Option { + if config.server.directory.is_none() { + return None; + } + + // Get directory, relative to config directory if known + match config.path.as_ref().and_then(|p| p.parent()) { + Some(config_dir) => Some(config_dir.join(config.server.directory.as_ref().unwrap())), + None => config.server.directory.clone(), + } + } +} + /// Time configuration. #[derive(Debug, Deserialize)] #[serde(default)] diff --git a/src/mc/server_properties.rs b/src/mc/server_properties.rs index aafd2bb..ea3c395 100644 --- a/src/mc/server_properties.rs +++ b/src/mc/server_properties.rs @@ -11,39 +11,39 @@ const EOL: &str = "\r\n"; /// Try to rewrite changes in server.properties file in dir. /// /// Prints an error and stops on failure. -pub fn rewrite_dir(dir: &Path, changes: HashMap<&str, String>) { +pub fn rewrite_dir>(dir: P, changes: HashMap<&str, String>) { if changes.is_empty() { return; } // Ensure directory exists - if !dir.is_dir() { + if !dir.as_ref().is_dir() { warn!(target: "lazymc", "Not rewriting {} file, configured server directory doesn't exist: {}", FILE, - dir.to_str().unwrap_or("?") + dir.as_ref().to_str().unwrap_or("?") ); return; } // Rewrite file - rewrite_file(&dir.join(FILE), changes) + rewrite_file(dir.as_ref().join(FILE), changes) } /// Try to rewrite changes in server.properties file. /// /// Prints an error and stops on failure. -pub fn rewrite_file(file: &Path, changes: HashMap<&str, String>) { +pub fn rewrite_file>(file: P, changes: HashMap<&str, String>) { if changes.is_empty() { return; } // File must exist - if !file.is_file() { + if !file.as_ref().is_file() { warn!(target: "lazymc", "Not writing {} file, not found at: {}", FILE, - file.to_str().unwrap_or("?"), + file.as_ref().to_str().unwrap_or("?"), ); return; } diff --git a/src/server.rs b/src/server.rs index ada6acb..c3ba6d0 100644 --- a/src/server.rs +++ b/src/server.rs @@ -12,7 +12,7 @@ use tokio::sync::Semaphore; use tokio::sync::{Mutex, RwLock, RwLockReadGuard}; use tokio::time; -use crate::config::Config; +use crate::config::{Config, Server as ConfigServer}; use crate::mc::ban::{BannedIp, BannedIps}; use crate::os; @@ -421,7 +421,7 @@ pub async fn invoke_server_cmd( cmd.kill_on_drop(true); // Set working directory - if let Some(ref dir) = config.server.directory { + if let Some(ref dir) = ConfigServer::server_directory(&config) { cmd.current_dir(dir); } diff --git a/src/service/ban_reload.rs b/src/service/ban_reload.rs index d7aa07b..bfe7fb7 100644 --- a/src/service/ban_reload.rs +++ b/src/service/ban_reload.rs @@ -6,7 +6,7 @@ use std::time::Duration; use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; -use crate::config::Config; +use crate::config::{Config, Server as ConfigServer}; use crate::mc::ban; use crate::server::Server; @@ -23,7 +23,7 @@ pub fn service(config: Arc, server: Arc) { } // Ensure server directory is set, it must exist - let dir = match &config.server.directory { + let dir = match ConfigServer::server_directory(&config) { Some(dir) => dir, None => { warn!(target: "lazymc", "Not blocking banned IPs, server directory not configured, unable to find {} file", ban::FILE); diff --git a/src/status.rs b/src/status.rs index 3a65102..689c4ed 100644 --- a/src/status.rs +++ b/src/status.rs @@ -12,7 +12,7 @@ use tokio::fs; use tokio::io::AsyncWriteExt; use tokio::net::TcpStream; -use crate::config::*; +use crate::config::{Config, Server as ConfigServer}; use crate::join; use crate::mc::favicon; use crate::proto::action; @@ -260,7 +260,7 @@ async fn server_status(client_info: &ClientInfo, config: &Config, server: &Serve /// This always returns a favicon, returning the default one if none is set. async fn server_favicon(config: &Config) -> String { // Get server dir - let dir = match config.server.directory.as_ref() { + let dir = match ConfigServer::server_directory(config) { Some(dir) => dir, None => return favicon::default_favicon(), };