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
This commit is contained in:
parent
835f0a36db
commit
0adcaf67c2
155
liberty.c
155
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
|
static void
|
||||||
get_xdg_config_dirs (struct str_vector *out)
|
get_xdg_config_dirs (struct str_vector *out)
|
||||||
{
|
{
|
||||||
@ -2692,10 +2721,75 @@ get_xdg_config_dirs (struct str_vector *out)
|
|||||||
str_free (&config_home);
|
str_free (&config_home);
|
||||||
|
|
||||||
const char *xdg_config_dirs;
|
const char *xdg_config_dirs;
|
||||||
if ((xdg_config_dirs = getenv ("XDG_CONFIG_DIRS")))
|
if (!(xdg_config_dirs = getenv ("XDG_CONFIG_DIRS")))
|
||||||
|
xdg_config_dirs = "/etc/xdg";
|
||||||
cstr_split_ignore_empty (xdg_config_dirs, ':', out);
|
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 *
|
static char *
|
||||||
try_expand_tilde (const char *filename)
|
try_expand_tilde (const char *filename)
|
||||||
{
|
{
|
||||||
@ -2727,65 +2821,6 @@ try_expand_tilde (const char *filename)
|
|||||||
return result;
|
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 *
|
static char *
|
||||||
resolve_filename (const char *filename, char *(*relative_cb) (const char *))
|
resolve_filename (const char *filename, char *(*relative_cb) (const char *))
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user