From 4c7ad485bf9e421508ae018bdbcad28e4ad88a70 Mon Sep 17 00:00:00 2001 From: emeric Date: Sun, 8 Mar 2026 21:30:11 +0100 Subject: [PATCH] Added basic checks to ensure configured directories in lms.conf exist, fixes #828 --- INSTALL.md | 8 ++++---- src/lms/main.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index b5d795b9..dbe9146a 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -45,7 +45,7 @@ __Optional dependencies__: __Notes__: * `libstb-dev` can be replaced by `libgraphicsmagick++1-dev` (the latter will likely use more RAM) -You also need _Wt4_, which is not packaged on _Debian_. See [installation instructions](https://www.webtoolkit.eu/wt/doc/reference/html/InstallationUnix.html).
+You also need _Wt4_, which is not packaged on _Debian_. See [installation instructions](https://www.webtoolkit.eu/wt/doc/reference/html/InstallationUnix.html). ### Build Get the latest stable release and build it: ```sh @@ -99,9 +99,9 @@ systemctl restart lms # Deployment __Note__: don't forget to give the _lms_ user read access to the music directory you want to scan. ## Configuration -_LMS_ uses a configuration file, installed by default in `/etc/lms.conf`. It is recommended to edit this file and change relevant settings (listen address, listen port, working directory, Subsonic API activation, deployment path, ...). -All other settings are set using the web interface (user management, scan settings, transcode settings, ...). -If a setting is not present in the configuration file, a hardcoded default value is used (the same as in the [default configuration file](conf/lms.conf)) +_LMS_ uses a configuration file installed by default at `/etc/lms.conf`. It is recommended to edit this file and adjust the relevant settings like the working directory, Wt resources path, listen address, listen port, etc. +All other settings are configured through the web interface (user management, scan settings, transcode settings, etc.). +If a setting is not present in the configuration file, a hardcoded default value is used (the same as in the [default configuration file](conf/lms.conf)). ## Authentication backends You can define which authentication backend to be used thanks to the `authentication-backend` option: * `internal` (default): _LMS_ uses an internal database to store users and their associated passwords (salted and hashed using [Bcrypt](https://en.wikipedia.org/wiki/Bcrypt)). Only the admin user can create, edit or remove other users. diff --git a/src/lms/main.cpp b/src/lms/main.cpp index 61890196..51f81923 100644 --- a/src/lms/main.cpp +++ b/src/lms/main.cpp @@ -17,6 +17,7 @@ * along with LMS. If not, see . */ +#include #include #include @@ -110,19 +111,58 @@ namespace lms throw core::LmsException{ "Invalid config value for 'jukebox-audio-backend'" }; } - std::vector generateWtConfig(std::string execPath) + std::error_code checkDirectoryAccessible(const std::filesystem::path& dir) + { + std::error_code ec; + + const std::filesystem::file_status status{ std::filesystem::status(dir, ec) }; + if (ec) + return ec; + + if (status.type() != std::filesystem::file_type::directory) + return std::make_error_code(std::errc::not_a_directory); + + const std::filesystem::directory_iterator it{ dir, ec }; + if (ec) + return ec; + + if (it != std::filesystem::directory_iterator{}) + { + it->status(ec); + if (ec) + return ec; + } + + return {}; + } + + std::vector generateWtConfig(const std::string& execPath) { core::IConfig& config{ *core::Service::get() }; std::vector args; - const std::filesystem::path wtConfigPath{ config.getPath("working-dir", "/var/lms") / "wt_config.xml" }; + const std::filesystem::path workingDirectoryPath{ config.getPath("working-dir", "/var/lms") }; + const std::filesystem::path wtConfigPath{ workingDirectoryPath / "wt_config.xml" }; const std::filesystem::path wtResourcesPath{ config.getPath("wt-resources", "/usr/share/Wt/resources") }; + const std::filesystem::path appRootPath{ config.getString("approot", "/usr/share/lms/approot") }; + + auto checkDirectoryExists{ [](const std::filesystem::path& directory, std::string_view settingName) { + std::string error; + + const std::error_code ec{ checkDirectoryAccessible(directory) }; + if (ec) + throw core::LmsException{ "Cannot access directory '" + directory.string() + "' specified in setting '" + std::string{ settingName } + "': " + ec.message() }; + } }; + + checkDirectoryExists(workingDirectoryPath, "working-dir"); + checkDirectoryExists(wtResourcesPath, "wt-resources"); + checkDirectoryExists(appRootPath, "approot"); args.push_back(execPath); args.push_back("--config=" + wtConfigPath.string()); args.push_back("--docroot=" + std::string{ config.getString("docroot", "/usr/share/lms/docroot/;/resources,/css,/images,/js,/favicon.ico") }); - args.push_back("--approot=" + std::string{ config.getString("approot", "/usr/share/lms/approot") }); + args.push_back("--approot=" + appRootPath.string()); args.push_back("--deploy-path=" + std::string{ config.getString("deploy-path", "/") }); if (!wtResourcesPath.empty()) args.push_back("--resources-dir=" + wtResourcesPath.string());