From 0adcaf67c23fdc2a5082aa11aefd4fdc0aafd70a Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Thu, 19 Nov 2015 13:27:12 +0100
Subject: Path searching changes
- fixed XDG config file search (didn't include /etc/xdg)
- added XDG data file search
- added a generic function to build custom resolvers
- code reshuffled
---
liberty.c | 141 +++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 88 insertions(+), 53 deletions(-)
diff --git a/liberty.c b/liberty.c
index 65bd3e8..290d4ef 100644
--- a/liberty.c
+++ b/liberty.c
@@ -2682,6 +2682,35 @@ get_xdg_home_dir (struct str *output, const char *var, const char *def)
}
}
+static char *
+resolve_relative_filename_generic
+ (struct str_vector *paths, const char *tail, const char *filename)
+{
+ struct str file;
+ str_init (&file);
+
+ char *result = NULL;
+ for (unsigned i = 0; i < paths->len; i++)
+ {
+ // As per XDG spec, relative paths are ignored
+ if (*paths->vector[i] != '/')
+ continue;
+
+ str_reset (&file);
+ str_append_printf (&file, "%s/%s%s", paths->vector[i], tail, filename);
+
+ struct stat st;
+ if (!stat (file.str, &st))
+ {
+ result = str_steal (&file);
+ break;
+ }
+ }
+
+ str_free (&file);
+ return result;
+}
+
static void
get_xdg_config_dirs (struct str_vector *out)
{
@@ -2692,72 +2721,47 @@ get_xdg_config_dirs (struct str_vector *out)
str_free (&config_home);
const char *xdg_config_dirs;
- if ((xdg_config_dirs = getenv ("XDG_CONFIG_DIRS")))
- cstr_split_ignore_empty (xdg_config_dirs, ':', out);
+ if (!(xdg_config_dirs = getenv ("XDG_CONFIG_DIRS")))
+ xdg_config_dirs = "/etc/xdg";
+ cstr_split_ignore_empty (xdg_config_dirs, ':', out);
}
static char *
-try_expand_tilde (const char *filename)
+resolve_relative_config_filename (const char *filename)
{
- size_t until_slash = strcspn (filename, "/");
- if (!until_slash)
- {
- struct str expanded;
- str_init (&expanded);
- str_append_env_path (&expanded, "HOME", false);
- str_append (&expanded, filename);
- return str_steal (&expanded);
- }
-
- int buf_len = sysconf (_SC_GETPW_R_SIZE_MAX);
- if (buf_len < 0)
- buf_len = 1024;
- struct passwd pwd, *success = NULL;
+ struct str_vector paths;
+ str_vector_init (&paths);
+ get_xdg_config_dirs (&paths);
+ char *result = resolve_relative_filename_generic
+ (&paths, PROGRAM_NAME "/", filename);
+ str_vector_free (&paths);
+ return result;
+}
- char *user = xstrndup (filename, until_slash);
- char *buf = xmalloc (buf_len);
- while (getpwnam_r (user, &pwd, buf, buf_len, &success) == ERANGE)
- buf = xrealloc (buf, buf_len <<= 1);
- free (user);
+static void
+get_xdg_data_dirs (struct str_vector *out)
+{
+ struct str data_home;
+ str_init (&data_home);
+ get_xdg_home_dir (&data_home, "XDG_DATA_HOME", ".local/share");
+ str_vector_add (out, data_home.str);
+ str_free (&data_home);
- char *result = NULL;
- if (success)
- result = xstrdup_printf ("%s%s", pwd.pw_dir, filename + until_slash);
- free (buf);
- return result;
+ const char *xdg_data_dirs;
+ if (!(xdg_data_dirs = getenv ("XDG_DATA_DIRS")))
+ xdg_data_dirs = "/usr/local/share/:/usr/share/";
+ cstr_split_ignore_empty (xdg_data_dirs, ':', out);
}
static char *
-resolve_relative_config_filename (const char *filename)
+resolve_relative_data_filename (const char *filename)
{
struct str_vector paths;
str_vector_init (&paths);
- get_xdg_config_dirs (&paths);
-
- struct str file;
- str_init (&file);
-
- char *result = NULL;
- for (unsigned i = 0; i < paths.len; i++)
- {
- // As per spec, relative paths are ignored
- if (*paths.vector[i] != '/')
- continue;
-
- str_reset (&file);
- str_append_printf (&file, "%s/" PROGRAM_NAME "/%s",
- paths.vector[i], filename);
-
- struct stat st;
- if (!stat (file.str, &st))
- {
- result = str_steal (&file);
- break;
- }
- }
-
+ get_xdg_data_dirs (&paths);
+ char *result = resolve_relative_filename_generic
+ (&paths, PROGRAM_NAME "/", filename);
str_vector_free (&paths);
- str_free (&file);
return result;
}
@@ -2786,6 +2790,37 @@ resolve_relative_runtime_filename (const char *filename)
return str_steal (&path);
}
+static char *
+try_expand_tilde (const char *filename)
+{
+ size_t until_slash = strcspn (filename, "/");
+ if (!until_slash)
+ {
+ struct str expanded;
+ str_init (&expanded);
+ str_append_env_path (&expanded, "HOME", false);
+ str_append (&expanded, filename);
+ return str_steal (&expanded);
+ }
+
+ int buf_len = sysconf (_SC_GETPW_R_SIZE_MAX);
+ if (buf_len < 0)
+ buf_len = 1024;
+ struct passwd pwd, *success = NULL;
+
+ char *user = xstrndup (filename, until_slash);
+ char *buf = xmalloc (buf_len);
+ while (getpwnam_r (user, &pwd, buf, buf_len, &success) == ERANGE)
+ buf = xrealloc (buf, buf_len <<= 1);
+ free (user);
+
+ char *result = NULL;
+ if (success)
+ result = xstrdup_printf ("%s%s", pwd.pw_dir, filename + until_slash);
+ free (buf);
+ return result;
+}
+
static char *
resolve_filename (const char *filename, char *(*relative_cb) (const char *))
{
--
cgit v1.2.3-70-g09d2