1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 obt/paths.c for the Openbox window manager
4 Copyright (c) 2003-2007 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
19 #include "obt/paths.h"
22 #ifdef HAVE_SYS_STAT_H
23 # include <sys/stat.h>
25 #ifdef HAVE_SYS_TYPES_H
26 # include <sys/types.h>
40 GSList *autostart_dirs;
43 static gint slist_path_cmp(const gchar *a, const gchar *b)
48 typedef GSList* (*GSListFunc) (gpointer list, gconstpointer data);
50 static GSList* slist_path_add(GSList *list, gpointer data, GSListFunc func)
57 if (!g_slist_find_custom(list, data, (GCompareFunc) slist_path_cmp))
58 list = func(list, data);
65 static GSList* split_paths(const gchar *paths)
72 spl = g_strsplit(paths, ":", -1);
73 for (it = spl; *it; ++it)
74 list = slist_path_add(list, *it, (GSListFunc) g_slist_append);
79 ObtPaths* obt_paths_new(void)
85 p = g_slice_new0(ObtPaths);
88 path = g_getenv("XDG_CONFIG_HOME");
89 if (path && path[0] != '\0') /* not unset or empty */
90 p->config_home = g_build_filename(path, NULL);
92 p->config_home = g_build_filename(g_get_home_dir(), ".config", NULL);
94 path = g_getenv("XDG_DATA_HOME");
95 if (path && path[0] != '\0') /* not unset or empty */
96 p->data_home = g_build_filename(path, NULL);
98 p->data_home = g_build_filename(g_get_home_dir(), ".local",
101 path = g_getenv("XDG_CACHE_HOME");
102 if (path && path[0] != '\0') /* not unset or empty */
103 p->cache_home = g_build_filename(path, NULL);
105 p->cache_home = g_build_filename(g_get_home_dir(), ".cache", NULL);
107 path = g_getenv("XDG_CONFIG_DIRS");
108 if (path && path[0] != '\0') /* not unset or empty */
109 p->config_dirs = split_paths(path);
111 p->config_dirs = slist_path_add(p->config_dirs,
113 (GSListFunc) g_slist_append);
114 p->config_dirs = slist_path_add(p->config_dirs,
118 (GSListFunc) g_slist_append);
120 p->config_dirs = slist_path_add(p->config_dirs,
121 g_strdup(p->config_home),
122 (GSListFunc) g_slist_prepend);
124 for (it = p->config_dirs; it; it = g_slist_next(it)) {
125 gchar *const s = g_strdup_printf("%s/autostart", (gchar*)it->data);
126 p->autostart_dirs = g_slist_append(p->autostart_dirs, s);
129 path = g_getenv("XDG_DATA_DIRS");
130 if (path && path[0] != '\0') /* not unset or empty */
131 p->data_dirs = split_paths(path);
133 p->data_dirs = slist_path_add(p->data_dirs,
135 (GSListFunc) g_slist_append);
136 p->data_dirs = slist_path_add(p->data_dirs,
139 "usr", "local", "share", NULL),
140 (GSListFunc) g_slist_append);
141 p->data_dirs = slist_path_add(p->data_dirs,
144 "usr", "share", NULL),
145 (GSListFunc) g_slist_append);
147 p->data_dirs = slist_path_add(p->data_dirs,
148 g_strdup(p->data_home),
149 (GSListFunc) g_slist_prepend);
153 void obt_paths_ref(ObtPaths *p)
158 void obt_paths_unref(ObtPaths *p)
160 if (p && --p->ref == 0) {
163 for (it = p->config_dirs; it; it = g_slist_next(it))
165 g_slist_free(p->config_dirs);
166 for (it = p->data_dirs; it; it = g_slist_next(it))
168 g_slist_free(p->data_dirs);
169 for (it = p->autostart_dirs; it; it = g_slist_next(it))
171 g_slist_free(p->autostart_dirs);
172 g_free(p->config_home);
173 g_free(p->data_home);
174 g_free(p->cache_home);
176 g_slice_free(ObtPaths, p);
180 gchar *obt_paths_expand_tilde(const gchar *f)
188 regex = g_regex_new("(?:^|(?<=[ \\t]))~(?=[/ \\t$])", G_REGEX_MULTILINE | G_REGEX_RAW, 0, NULL);
189 ret = g_regex_replace_literal(regex, f, -1, 0, g_get_home_dir(), 0, NULL);
190 g_regex_unref(regex);
195 gboolean obt_paths_mkdir(const gchar *path, gint mode)
199 g_return_val_if_fail(path != NULL, FALSE);
200 g_return_val_if_fail(path[0] != '\0', FALSE);
202 if (!g_file_test(path, G_FILE_TEST_IS_DIR))
203 if (mkdir(path, mode) == -1)
209 gboolean obt_paths_mkdir_path(const gchar *path, gint mode)
213 g_return_val_if_fail(path != NULL, FALSE);
214 g_return_val_if_fail(path[0] == '/', FALSE);
216 if (!g_file_test(path, G_FILE_TEST_IS_DIR)) {
221 while ((e = strchr(e + 1, '/'))) {
223 if (!(ret = obt_paths_mkdir(c, mode)))
224 goto parse_mkdir_path_end;
227 ret = obt_paths_mkdir(c, mode);
229 parse_mkdir_path_end:
236 const gchar* obt_paths_config_home(ObtPaths *p)
238 return p->config_home;
241 const gchar* obt_paths_data_home(ObtPaths *p)
246 const gchar* obt_paths_cache_home(ObtPaths *p)
248 return p->cache_home;
251 GSList* obt_paths_config_dirs(ObtPaths *p)
253 return p->config_dirs;
256 GSList* obt_paths_data_dirs(ObtPaths *p)
261 GSList* obt_paths_autostart_dirs(ObtPaths *p)
263 return p->autostart_dirs;