[PATCH] config-parser: Honor the XDG_CONFIG_DIRS environment variable

Othman, Ossama ossama.othman at intel.com
Fri May 10 16:06:41 PDT 2013


Hi,

Minor correction to my previous patch.  This revision corrects a small leak
in config_file_path_xdg_config_dirs().

Thanks!
-Ossama

---


Search for a given config file in the directories listed in
$XDG_CONFIG_DIRS if it wasn't found in $XDG_CONFIG_HOME or ~/.config.
This allows packages to install custom config files in
/etc/xdg/weston, for example, thus allowing them to avoid dealing with
home directories.

Signed-off-by: Ossama Othman <ossama.othman at intel.com>
---
 shared/config-parser.c |  128
+++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 105 insertions(+), 23 deletions(-)

diff --git a/shared/config-parser.c b/shared/config-parser.c
index 10ff86a..a781274 100644
--- a/shared/config-parser.c
+++ b/shared/config-parser.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <assert.h>
 #include <ctype.h>
+#include <unistd.h>

 #include "config-parser.h"

@@ -95,6 +96,9 @@ parse_config_file(const char *path,
  const struct config_section *current = NULL;
  int i;

+ if (path == NULL)
+ return -1;
+
  fp = fopen(path, "r");
  if (fp == NULL) {
  fprintf(stderr, "couldn't open %s\n", path);
@@ -151,37 +155,115 @@ parse_config_file(const char *path,
  return 0;
 }

+static char *
+config_file_path_xdg_config_home(const char *name)
+{
+ const char *config_dir = getenv("XDG_CONFIG_HOME");
+
+ if (config_dir) {
+ size_t size = strlen(config_dir) + 1 + strlen(name) + 1;
+ char *path = malloc(size);
+
+ /* TOCTOU race here.  Ideally we should open the file
+ * and return a handle to it. */
+ if (path &&
+    snprintf(path, size, "%s/%s", config_dir, name) > 0 &&
+    access(path, R_OK) == 0)
+ return path;
+
+ free(path);
+ }
+
+ return NULL;
+}
+
+static char *
+config_file_path_home(const char *name)
+{
+ const char *home_dir = getenv("HOME");
+
+ if (home_dir) {
+ const char dotconf[] = "/.config/";
+
+ size_t size = strlen(home_dir) + sizeof dotconf + strlen(name);
+ char *path = malloc(size);
+
+ if (path &&
+    snprintf(path, size, "%s%s%s",
+     home_dir, dotconf, name) > 0 &&
+    access(path, R_OK) == 0)
+ return path;
+
+ free(path);
+ }
+
+ return NULL;
+}
+
+static char *
+config_file_path_xdg_config_dirs(const char *name)
+{
+ const char *config_dirs = getenv("XDG_CONFIG_DIRS");
+
+ if (config_dirs) {
+ const char weston_dir[] = "/weston/";
+ char *config_dir, *saveptr, *dirs;
+ char *path = NULL;
+ size_t size;
+
+ size = strlen(config_dirs) + 1;
+ dirs = malloc(size);
+ if (!dirs)
+ return NULL;
+
+ /* strtok_r() modifies the first argument.  Avoid
+ * clobbering the process environment. */
+ strncpy(dirs, config_dirs, size);
+
+ for (config_dir = strtok_r(dirs, ":", &saveptr);
+     config_dir != NULL;
+     config_dir = strtok_r(NULL, ":", &saveptr)) {
+ size = strlen(config_dir) +
+ sizeof weston_dir + strlen(name);
+ path = realloc(path, size);
+
+ if (path &&
+    snprintf(path, size, "%s%s%s",
+     config_dir, weston_dir, name) > 0 &&
+    access(path, R_OK) == 0) {
+ free(dirs);
+ return path;
+ }
+ }
+
+ free(dirs);
+ free(path);
+ }
+
+ return NULL;
+}
+
 char *
 config_file_path(const char *name)
 {
- const char dotconf[] = "/.config/";
- const char *config_dir;
- const char *home_dir;
  char *path;
- size_t size;
-
- config_dir = getenv("XDG_CONFIG_HOME");
- if (!config_dir) {
- home_dir = getenv("HOME");
- if (!home_dir) {
- fprintf(stderr, "HOME is not set, using cwd.\n");
- return strdup(name);
- }

- size = strlen(home_dir) + sizeof dotconf + strlen(name);
- path = malloc(size);
- if (!path)
- return NULL;
+ /* Precedence is given to config files in the home directory,
+ * and then to directories listed in XDG_CONFIG_DIRS. */

- snprintf(path, size, "%s%s%s", home_dir, dotconf, name);
- return path;
- }
+ path = config_file_path_xdg_config_home(name);
+
+ if (!path)
+ path = config_file_path_home(name);
+
+ if (!path)
+ path = config_file_path_xdg_config_dirs(name);

- size = strlen(config_dir) + 1 + strlen(name) + 1;
- path = malloc(size);
  if (!path)
- return NULL;
+ fprintf(stderr,
+ "config file \"%s\" not found in "
+ "$XDG_CONFIG_{HOME,DIRS} or ~/.config\n",
+ name);

- snprintf(path, size, "%s/%s", config_dir, name);
  return path;
 }
-- 
1.7.10.4
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130510/834a52b2/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-config-parser-Honor-the-XDG_CONFIG_DIRS-environment-.patch
Type: application/octet-stream
Size: 4383 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20130510/834a52b2/attachment-0001.obj>


More information about the wayland-devel mailing list