diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2015-11-19 13:27:12 +0100 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2015-11-19 13:27:12 +0100 |
commit | 0adcaf67c23fdc2a5082aa11aefd4fdc0aafd70a (patch) | |
tree | 8760d4d9b166710f3e9e42bd731238051b0a6320 | |
parent | 835f0a36db4e006b336ae6d41ae87d1195af7ec7 (diff) | |
download | liberty-0adcaf67c23fdc2a5082aa11aefd4fdc0aafd70a.tar.gz liberty-0adcaf67c23fdc2a5082aa11aefd4fdc0aafd70a.tar.xz liberty-0adcaf67c23fdc2a5082aa11aefd4fdc0aafd70a.zip |
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
-rw-r--r-- | liberty.c | 141 |
1 files changed, 88 insertions, 53 deletions
@@ -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; } @@ -2787,6 +2791,37 @@ resolve_relative_runtime_filename (const char *filename) } 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 *)) { // Absolute path is absolute |