From 0adcaf67c23fdc2a5082aa11aefd4fdc0aafd70a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?=
Date: Thu, 19 Nov 2015 13:27:12 +0100
Subject: [PATCH] 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 | 157 +++++++++++++++++++++++++++++++++---------------------
1 file changed, 96 insertions(+), 61 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,8 +2721,73 @@ 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 *
+resolve_relative_config_filename (const char *filename)
+{
+ 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;
+}
+
+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);
+
+ 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_data_filename (const char *filename)
+{
+ struct str_vector paths;
+ str_vector_init (&paths);
+ get_xdg_data_dirs (&paths);
+ char *result = resolve_relative_filename_generic
+ (&paths, PROGRAM_NAME "/", filename);
+ str_vector_free (&paths);
+ return result;
+}
+
+static char *
+resolve_relative_runtime_filename (const char *filename)
+{
+ struct str path;
+ str_init (&path);
+
+ const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
+ if (runtime_dir && *runtime_dir == '/')
+ str_append (&path, runtime_dir);
+ else
+ get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
+ str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename);
+
+ // Try to create the file's ancestors;
+ // typically the user will want to immediately create a file in there
+ const char *last_slash = strrchr (path.str, '/');
+ if (last_slash && last_slash != path.str)
+ {
+ char *copy = xstrndup (path.str, last_slash - path.str);
+ (void) mkdir_with_parents (copy, NULL);
+ free (copy);
+ }
+ return str_steal (&path);
}
static char *
@@ -2727,65 +2821,6 @@ try_expand_tilde (const char *filename)
return result;
}
-static char *
-resolve_relative_config_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;
- }
- }
-
- str_vector_free (&paths);
- str_free (&file);
- return result;
-}
-
-static char *
-resolve_relative_runtime_filename (const char *filename)
-{
- struct str path;
- str_init (&path);
-
- const char *runtime_dir = getenv ("XDG_RUNTIME_DIR");
- if (runtime_dir && *runtime_dir == '/')
- str_append (&path, runtime_dir);
- else
- get_xdg_home_dir (&path, "XDG_DATA_HOME", ".local/share");
- str_append_printf (&path, "/%s/%s", PROGRAM_NAME, filename);
-
- // Try to create the file's ancestors;
- // typically the user will want to immediately create a file in there
- const char *last_slash = strrchr (path.str, '/');
- if (last_slash && last_slash != path.str)
- {
- char *copy = xstrndup (path.str, last_slash - path.str);
- (void) mkdir_with_parents (copy, NULL);
- free (copy);
- }
- return str_steal (&path);
-}
-
static char *
resolve_filename (const char *filename, char *(*relative_cb) (const char *))
{