[v1] libcamera: pipeline_handler: Try more configuration file paths
diff mbox series

Message ID 20261017111758.633101-1-robert.mader@collabora.com
State New
Headers show
Series
  • [v1] libcamera: pipeline_handler: Try more configuration file paths
Related show

Commit Message

Robert Mader Oct. 17, 2026, 11:17 a.m. UTC
Similar to the global configuration file - configuration.yaml - check
the user- and system-configuration paths for pipeline handlers.

This is particularly useful on immutable OSs which typically don't allow
writes to /usr/share.

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Closes https://gitlab.freedesktop.org/camera/libcamera/-/work_items/364
---
 src/libcamera/pipeline_handler.cpp | 44 ++++++++++++++++++++++--------
 1 file changed, 33 insertions(+), 11 deletions(-)

Comments

Barnabás Pőcze Oct. 19, 2026, 1:01 p.m. UTC | #1
Hi

2026. 10. 17. 13:17 keltezéssel, Robert Mader írta:
> Similar to the global configuration file - configuration.yaml - check
> the user- and system-configuration paths for pipeline handlers.
> 
> This is particularly useful on immutable OSs which typically don't allow
> writes to /usr/share.
> 
> Signed-off-by: Robert Mader <robert.mader@collabora.com>
> Closes https://gitlab.freedesktop.org/camera/libcamera/-/work_items/364
> ---

I think this change makes sense. But I think what could be improved is the removal
of the duplication. Maybe a function like

   findConfigurationFile(std::filesystem::path subdir, std::filesystem::path name)

that will go through

   - (HOME)/subdir/name
   - LIBCAMERA_SYSCONF_DIR/subdir/name
   - LIBCAMERA_DATA_DIR/subdir/name

or something like that. Not sure though.



>   src/libcamera/pipeline_handler.cpp | 44 ++++++++++++++++++++++--------
>   1 file changed, 33 insertions(+), 11 deletions(-)
> 
> diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
> index a803f6208c32..c23a11026279 100644
> --- a/src/libcamera/pipeline_handler.cpp
> +++ b/src/libcamera/pipeline_handler.cpp
> @@ -628,6 +628,8 @@ void PipelineHandler::cancelRequest(Request *request)
>    *
>    * - If libcamera is not installed, the src/libcamera/pipeline/\<subdir\>/data/
>    *   directory within the source tree ; otherwise
> + * - The user configuration (~/.config/libcamera/pipeline/\<subdir\>) directory.
> + * - The system configuration (etc/libcamera/pipeline/\<subdir\>) directory.
>    * - The system data (share/libcamera/pipeline/\<subdir\>) directory.
>    *
>    * The system directories are not searched if libcamera is not installed.
> @@ -639,9 +641,8 @@ std::string PipelineHandler::configurationFile(const std::string &subdir,
>   					       const std::string &name,
>   					       bool silent) const
>   {
> -	std::string confPath;
> +	std::vector<std::string> confPaths;
>   	struct stat statbuf;
> -	int ret;
>   
>   	std::string root = utils::libcameraSourcePath();
>   	if (!root.empty()) {
> @@ -652,25 +653,46 @@ std::string PipelineHandler::configurationFile(const std::string &subdir,
>   		 * subdirectory of the corresponding pipeline handler.
>   		 */
>   		std::string confDir = root + "src/libcamera/pipeline/";
> -		confPath = confDir + subdir + "/data/" + name;
> +		confPaths.push_back(confDir + subdir + "/data/" + name);
>   
>   		LOG(Pipeline, Info)
>   			<< "libcamera is not installed. Loading platform configuration file from '"
> -			<< confPath << "'";
> +			<< confPaths.front() << "'";
>   	} else {
>   		/* Else look in the system locations. */
> -		confPath = std::string(LIBCAMERA_DATA_DIR)
> -				+ "/pipeline/" + subdir + '/' + name;
> +		std::filesystem::path userConfigurationDirectory;
> +		const char *xdgConfigHome = utils::secure_getenv("XDG_CONFIG_HOME");
> +		if (xdgConfigHome) {
> +			userConfigurationDirectory = xdgConfigHome;
> +		} else {
> +			const char *home = utils::secure_getenv("HOME");
> +			if (home)
> +				userConfigurationDirectory =
> +					std::filesystem::path(home) / ".config";
> +		}
> +
> +		confPaths.push_back(std::string(userConfigurationDirectory) + "/libcamera");
> +		confPaths.push_back(std::string(LIBCAMERA_SYSCONF_DIR));
> +		confPaths.push_back(std::string(LIBCAMERA_DATA_DIR));
> +
> +		for (std::string &confPath : confPaths) {
> +			confPath += "/pipeline/" + subdir + '/' + name;
> +		}
>   	}
>   
> -	ret = stat(confPath.c_str(), &statbuf);
> -	if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
> -		return confPath;
> +	for (const std::string &confPath : confPaths) {
> +		int ret = stat(confPath.c_str(), &statbuf);
> +		if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) {
> +			LOG(Pipeline, Debug)
> +				<< "Loading platform configuration file from '"
> +				<< confPath << "'";
> +			return confPath;
> +		}
> +	}
>   
>   	if (!silent)
>   		LOG(Pipeline, Error)
> -			<< "Configuration file '" << confPath
> -			<< "' not found for pipeline handler '"
> +			<< "Configuration file not found for pipeline handler '"
>   			<< PipelineHandler::name() << "'";
>   
>   	return std::string();

Patch
diff mbox series

diff --git a/src/libcamera/pipeline_handler.cpp b/src/libcamera/pipeline_handler.cpp
index a803f6208c32..c23a11026279 100644
--- a/src/libcamera/pipeline_handler.cpp
+++ b/src/libcamera/pipeline_handler.cpp
@@ -628,6 +628,8 @@  void PipelineHandler::cancelRequest(Request *request)
  *
  * - If libcamera is not installed, the src/libcamera/pipeline/\<subdir\>/data/
  *   directory within the source tree ; otherwise
+ * - The user configuration (~/.config/libcamera/pipeline/\<subdir\>) directory.
+ * - The system configuration (etc/libcamera/pipeline/\<subdir\>) directory.
  * - The system data (share/libcamera/pipeline/\<subdir\>) directory.
  *
  * The system directories are not searched if libcamera is not installed.
@@ -639,9 +641,8 @@  std::string PipelineHandler::configurationFile(const std::string &subdir,
 					       const std::string &name,
 					       bool silent) const
 {
-	std::string confPath;
+	std::vector<std::string> confPaths;
 	struct stat statbuf;
-	int ret;
 
 	std::string root = utils::libcameraSourcePath();
 	if (!root.empty()) {
@@ -652,25 +653,46 @@  std::string PipelineHandler::configurationFile(const std::string &subdir,
 		 * subdirectory of the corresponding pipeline handler.
 		 */
 		std::string confDir = root + "src/libcamera/pipeline/";
-		confPath = confDir + subdir + "/data/" + name;
+		confPaths.push_back(confDir + subdir + "/data/" + name);
 
 		LOG(Pipeline, Info)
 			<< "libcamera is not installed. Loading platform configuration file from '"
-			<< confPath << "'";
+			<< confPaths.front() << "'";
 	} else {
 		/* Else look in the system locations. */
-		confPath = std::string(LIBCAMERA_DATA_DIR)
-				+ "/pipeline/" + subdir + '/' + name;
+		std::filesystem::path userConfigurationDirectory;
+		const char *xdgConfigHome = utils::secure_getenv("XDG_CONFIG_HOME");
+		if (xdgConfigHome) {
+			userConfigurationDirectory = xdgConfigHome;
+		} else {
+			const char *home = utils::secure_getenv("HOME");
+			if (home)
+				userConfigurationDirectory =
+					std::filesystem::path(home) / ".config";
+		}
+
+		confPaths.push_back(std::string(userConfigurationDirectory) + "/libcamera");
+		confPaths.push_back(std::string(LIBCAMERA_SYSCONF_DIR));
+		confPaths.push_back(std::string(LIBCAMERA_DATA_DIR));
+
+		for (std::string &confPath : confPaths) {
+			confPath += "/pipeline/" + subdir + '/' + name;
+		}
 	}
 
-	ret = stat(confPath.c_str(), &statbuf);
-	if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
-		return confPath;
+	for (const std::string &confPath : confPaths) {
+		int ret = stat(confPath.c_str(), &statbuf);
+		if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG) {
+			LOG(Pipeline, Debug)
+				<< "Loading platform configuration file from '"
+				<< confPath << "'";
+			return confPath;
+		}
+	}
 
 	if (!silent)
 		LOG(Pipeline, Error)
-			<< "Configuration file '" << confPath
-			<< "' not found for pipeline handler '"
+			<< "Configuration file not found for pipeline handler '"
 			<< PipelineHandler::name() << "'";
 
 	return std::string();