<div dir="ltr"><div style>Hi,</div><div style><br></div><div style>Minor correction to my previous patch. This revision corrects a small leak in config_file_path_xdg_config_dirs().</div><div style><br></div><div style>Thanks!</div>
<div style>-Ossama</div><div style><br></div><div style>---</div><div><br></div><br><div class="gmail_extra"><div class="gmail_extra">Search for a given config file in the directories listed in</div><div class="gmail_extra">
$XDG_CONFIG_DIRS if it wasn't found in $XDG_CONFIG_HOME or ~/.config.</div><div class="gmail_extra">This allows packages to install custom config files in</div><div class="gmail_extra">/etc/xdg/weston, for example, thus allowing them to avoid dealing with</div>
<div class="gmail_extra">home directories.</div><div class="gmail_extra"><br></div><div class="gmail_extra">Signed-off-by: Ossama Othman <<a href="mailto:ossama.othman@intel.com">ossama.othman@intel.com</a>></div><div class="gmail_extra">
---</div><div class="gmail_extra"> shared/config-parser.c | 128 +++++++++++++++++++++++++++++++++++++++---------</div><div class="gmail_extra"> 1 file changed, 105 insertions(+), 23 deletions(-)</div><div class="gmail_extra">
<br></div><div class="gmail_extra">diff --git a/shared/config-parser.c b/shared/config-parser.c</div><div class="gmail_extra">index 10ff86a..a781274 100644</div><div class="gmail_extra">--- a/shared/config-parser.c</div><div class="gmail_extra">
+++ b/shared/config-parser.c</div><div class="gmail_extra">@@ -25,6 +25,7 @@</div><div class="gmail_extra"> #include <stdlib.h></div><div class="gmail_extra"> #include <assert.h></div><div class="gmail_extra">
#include <ctype.h></div><div class="gmail_extra">+#include <unistd.h></div><div class="gmail_extra"> </div><div class="gmail_extra"> #include "config-parser.h"</div><div class="gmail_extra"> </div><div class="gmail_extra">
@@ -95,6 +96,9 @@ parse_config_file(const char *path,</div><div class="gmail_extra"> <span class="" style="white-space:pre"> </span>const struct config_section *current = NULL;</div><div class="gmail_extra"> <span class="" style="white-space:pre"> </span>int i;</div>
<div class="gmail_extra"> </div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (path == NULL)</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return -1;</div><div class="gmail_extra">
+</div><div class="gmail_extra"> <span class="" style="white-space:pre"> </span>fp = fopen(path, "r");</div><div class="gmail_extra"> <span class="" style="white-space:pre"> </span>if (fp == NULL) {</div><div class="gmail_extra">
<span class="" style="white-space:pre"> </span>fprintf(stderr, "couldn't open %s\n", path);</div><div class="gmail_extra">@@ -151,37 +155,115 @@ parse_config_file(const char *path,</div><div class="gmail_extra">
<span class="" style="white-space:pre"> </span>return 0;</div><div class="gmail_extra"> }</div><div class="gmail_extra"> </div><div class="gmail_extra">+static char *</div><div class="gmail_extra">+config_file_path_xdg_config_home(const char *name)</div>
<div class="gmail_extra">+{</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>const char *config_dir = getenv("XDG_CONFIG_HOME");</div><div class="gmail_extra">+</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>if (config_dir) {</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>size_t size = strlen(config_dir) + 1 + strlen(name) + 1;</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>char *path = malloc(size);</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>/* TOCTOU race here. Ideally we should open the file</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span> * and return a handle to it. */</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (path &&</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span> snprintf(path, size, "%s/%s", config_dir, name) > 0 &&</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> access(path, R_OK) == 0)</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return path;</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>free(path);</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>}</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return NULL;</div><div class="gmail_extra">+}</div><div class="gmail_extra">
+</div><div class="gmail_extra">+static char *</div><div class="gmail_extra">+config_file_path_home(const char *name)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>const char *home_dir = getenv("HOME");</div>
<div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (home_dir) {</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>const char dotconf[] = "/.config/";</div>
<div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>size_t size = strlen(home_dir) + sizeof dotconf + strlen(name);</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>char *path = malloc(size);</div>
<div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (path &&</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> snprintf(path, size, "%s%s%s",</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span> home_dir, dotconf, name) > 0 &&</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> access(path, R_OK) == 0)</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return path;</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>free(path);</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>}</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return NULL;</div><div class="gmail_extra">+}</div><div class="gmail_extra">
+</div><div class="gmail_extra">+static char *</div><div class="gmail_extra">+config_file_path_xdg_config_dirs(const char *name)</div><div class="gmail_extra">+{</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>const char *config_dirs = getenv("XDG_CONFIG_DIRS");</div>
<div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (config_dirs) {</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>const char weston_dir[] = "/weston/";</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>char *config_dir, *saveptr, *dirs;</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>char *path = NULL;</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>size_t size;</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>size = strlen(config_dirs) + 1;</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>dirs = malloc(size);</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (!dirs)</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return NULL;</div>
<div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>/* strtok_r() modifies the first argument. Avoid</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> * clobbering the process environment. */</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>strncpy(dirs, config_dirs, size);</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>for (config_dir = strtok_r(dirs, ":", &saveptr);</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span> config_dir != NULL;</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> config_dir = strtok_r(NULL, ":", &saveptr)) {</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>size = strlen(config_dir) +</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>sizeof weston_dir + strlen(name);</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>path = realloc(path, size);</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (path &&</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span> snprintf(path, size, "%s%s%s",</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> config_dir, weston_dir, name) > 0 &&</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span> access(path, R_OK) == 0) {</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>free(dirs);</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>return path;</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>}</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>}</div>
<div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>free(dirs);</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>free(path);</div><div class="gmail_extra">
+<span class="" style="white-space:pre"> </span>}</div><div class="gmail_extra">+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>return NULL;</div><div class="gmail_extra">+}</div><div class="gmail_extra">
+</div><div class="gmail_extra"> char *</div><div class="gmail_extra"> config_file_path(const char *name)</div><div class="gmail_extra"> {</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>const char dotconf[] = "/.config/";</div>
<div class="gmail_extra">-<span class="" style="white-space:pre"> </span>const char *config_dir;</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>const char *home_dir;</div><div class="gmail_extra">
<span class="" style="white-space:pre"> </span>char *path;</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>size_t size;</div><div class="gmail_extra">-</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>config_dir = getenv("XDG_CONFIG_HOME");</div>
<div class="gmail_extra">-<span class="" style="white-space:pre"> </span>if (!config_dir) {</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>home_dir = getenv("HOME");</div><div class="gmail_extra">
-<span class="" style="white-space:pre"> </span>if (!home_dir) {</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>fprintf(stderr, "HOME is not set, using cwd.\n");</div><div class="gmail_extra">
-<span class="" style="white-space:pre"> </span>return strdup(name);</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>}</div><div class="gmail_extra"> </div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>size = strlen(home_dir) + sizeof dotconf + strlen(name);</div>
<div class="gmail_extra">-<span class="" style="white-space:pre"> </span>path = malloc(size);</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>if (!path)</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>return NULL;</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>/* Precedence is given to config files in the home directory,</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span> * and then to directories listed in XDG_CONFIG_DIRS. */</div>
<div class="gmail_extra"> </div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>snprintf(path, size, "%s%s%s", home_dir, dotconf, name);</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>return path;</div>
<div class="gmail_extra">-<span class="" style="white-space:pre"> </span>}</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>path = config_file_path_xdg_config_home(name);</div><div class="gmail_extra">
+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (!path)</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>path = config_file_path_home(name);</div><div class="gmail_extra">
+</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>if (!path)</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>path = config_file_path_xdg_config_dirs(name);</div>
<div class="gmail_extra"> </div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>size = strlen(config_dir) + 1 + strlen(name) + 1;</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>path = malloc(size);</div>
<div class="gmail_extra"> <span class="" style="white-space:pre"> </span>if (!path)</div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>return NULL;</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>fprintf(stderr,</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>"config file \"%s\" not found in "</div><div class="gmail_extra">+<span class="" style="white-space:pre"> </span>"$XDG_CONFIG_{HOME,DIRS} or ~/.config\n",</div>
<div class="gmail_extra">+<span class="" style="white-space:pre"> </span>name);</div><div class="gmail_extra"> </div><div class="gmail_extra">-<span class="" style="white-space:pre"> </span>snprintf(path, size, "%s/%s", config_dir, name);</div>
<div class="gmail_extra"> <span class="" style="white-space:pre"> </span>return path;</div><div class="gmail_extra"> }</div><div class="gmail_extra">-- </div><div class="gmail_extra">1.7.10.4</div></div></div>