1 /* Copyright (C) 2016-2018 Shengyu Zhang <i@silverrainz.me>
2 *
3 * This file is part of Srain.
4 *
5 * Srain is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20 * @file path.c
21 * @brief Get application data files' path
22 * @author Shengyu Zhang <i@silverrainz.me>
23 * @version 0.06.2
24 * @date 2018-12-15
25 */
26
27
28 #include <sys/stat.h>
29 #include <glib.h>
30 #include <glib/gstdio.h>
31 #include <fcntl.h>
32 #include <errno.h>
33
34 #include "meta.h"
35 #include "log.h"
36 #include "i18n.h"
37
38 #define DEFAULT_FILE_MODE (S_IRUSR | S_IWUSR)
39 #define DEFAULT_DIR_MODE (S_IRWXU)
40
41 static SrnRet create_file_if_not_exist(const char *path);
42 static SrnRet create_dir_if_not_exist(const char *path);
43
44 /**
45 * @brief srn_get_theme_file returns the path of theme file with specified name.
46 * If the file is not found, returns NULL.
47 *
48 * @param fname
49 *
50 * @return NULL or path to the theme file, must be freed by g_free.
51 */
srn_get_theme_file(const char * name)52 char *srn_get_theme_file(const char *name){
53 char *path;
54
55 path = g_build_filename(PACKAGE_DATA_DIR, PACKAGE, "themes", name, NULL);
56
57 if (g_file_test(path, G_FILE_TEST_EXISTS)){
58 return path;
59 }
60
61 g_free(path);
62 return NULL;
63 }
64
srn_get_user_config_file()65 char *srn_get_user_config_file(){
66 char *path;
67 SrnRet ret;
68
69 path = g_build_filename(g_get_user_config_dir(), PACKAGE, "srain.cfg", NULL);
70
71 ret = create_file_if_not_exist(path);
72 if (!RET_IS_OK(ret)){
73 WARN_FR("Failed to create user configuration file: %1$s", RET_MSG(ret));
74
75 g_free(path);
76 return NULL;
77 }
78
79 return path;
80 }
81
srn_get_system_config_file()82 char *srn_get_system_config_file(){
83 char *path;
84
85 path = g_build_filename(PACKAGE_CONFIG_DIR, PACKAGE, "builtin.cfg", NULL);
86
87 if (g_file_test(path, G_FILE_TEST_EXISTS)){
88 return path;
89 }
90
91 // System configuration file should always exist
92 WARN_FR("'%s' not found", path);
93
94 g_free(path);
95 return NULL;
96 }
97
98 // FIXME: actually it only create the dir.
srn_create_log_file(const char * srv_name,const char * fname)99 char *srn_create_log_file(const char *srv_name, const char *fname){
100 char *path;
101 SrnRet ret;
102
103 // $XDG_DATA_HOME/srain/logs/<srv_name>/<fname>
104 path = g_build_filename(g_get_user_data_dir(),
105 PACKAGE, "logs", srv_name, fname, NULL);
106
107 ret = create_file_if_not_exist(path);
108 if (!RET_IS_OK(ret)){
109 WARN_FR("Failed to create log file: %1$s", RET_MSG(ret));
110
111 g_free(path);
112 return NULL;
113 }
114
115 return path;
116 }
117
118 /**
119 * @brief srn_create_user_files creates users files which required for
120 * running of Srain
121 *
122 * @return SRN_OK if all required files are created or already existent
123 *
124 * User fils including:
125 *
126 * - $XDG_CONFIG_HOME/srain/
127 * - $XDG_CONFIG_HOME/srain/srain.cfg
128 * - $XDG_CACHE_HOME/srain/
129 * - $XDG_DATA_HOME/srain/logs
130 *
131 * FIXME: not in use
132 */
srn_create_user_files()133 SrnRet srn_create_user_files(){
134 SrnRet ret;
135 char *path;
136
137 path = g_build_filename( // $XDG_CONFIG_HOME/srain/
138 g_get_user_config_dir(),
139 PACKAGE,
140 NULL);
141 ret = create_dir_if_not_exist(path);
142 g_free(path);
143 if (!RET_IS_OK(ret)){
144 ret = RET_ERR(_("Failed to create user configuration directory: %1$s"),
145 RET_MSG(ret));
146 goto FIN;
147 }
148
149 // $XDG_CONFIG_HOME/srain/srain.cfg
150 path = g_build_filename(g_get_user_config_dir(), PACKAGE, "srain.cfg", NULL);
151 ret = create_file_if_not_exist(path);
152 g_free(path);
153 if (!RET_IS_OK(ret)){
154 ret = RET_ERR(_("Failed to create user configuration file: %1$s"),
155 RET_MSG(ret));
156 goto FIN;
157 }
158
159 // $XDG_CACHE_HOME/srain/
160 path = g_build_filename(g_get_user_cache_dir(), PACKAGE, NULL);
161 ret = create_dir_if_not_exist(path);
162 g_free(path);
163 if (!RET_IS_OK(ret)){
164 ret = RET_ERR(_("Failed to create user cache directory: %1$s"),
165 RET_MSG(ret));
166 goto FIN;
167 }
168
169 // $XDG_DATA_HOME/srain/
170 path = g_build_filename(g_get_user_data_dir(), PACKAGE, NULL);
171 ret = create_dir_if_not_exist(path);
172 g_free(path);
173 if (!RET_IS_OK(ret)){
174 ret = RET_ERR(_("Failed to create user data directory: %1$s"),
175 RET_MSG(ret));
176 goto FIN;
177 }
178
179 // $XDG_DATA_HOME/srain/logs
180 path = g_build_filename(g_get_user_data_dir(), PACKAGE, "logs", NULL);
181 ret = create_dir_if_not_exist(path);
182 g_free(path);
183 if (!RET_IS_OK(ret)){
184 ret = RET_ERR(_("Failed to create chat logs directory: %1$s"),
185 RET_MSG(ret));
186 goto FIN;
187 }
188
189 ret = SRN_OK;
190 FIN:
191 return ret;
192 }
193
create_dir_if_not_exist(const char * path)194 SrnRet create_dir_if_not_exist(const char *path) {
195 if (g_file_test(path, G_FILE_TEST_IS_DIR)){
196 return SRN_OK;
197 }
198 if (g_file_test(path, G_FILE_TEST_EXISTS)){
199 return RET_ERR(_("Not a directory"));
200 }
201
202 if (g_mkdir_with_parents(path, DEFAULT_DIR_MODE) == -1) {
203 return RET_ERR("%s", g_strerror(errno));
204 }
205
206 return SRN_OK;
207 }
208
create_file_if_not_exist(const char * path)209 SrnRet create_file_if_not_exist(const char *path) {
210 int fd;
211 char *dir;
212 SrnRet ret;
213
214 if (g_file_test(path, G_FILE_TEST_IS_REGULAR)){
215 return SRN_OK;
216 }
217 if (g_file_test(path, G_FILE_TEST_EXISTS)){
218 return RET_ERR(_("Not a regular file"));
219 }
220
221 dir = g_path_get_dirname(path);
222 ret = create_dir_if_not_exist(dir);
223 g_free(dir);
224 if (!RET_IS_OK(ret)){
225 return ret;
226 }
227
228 if ((fd = g_creat(path, DEFAULT_FILE_MODE)) == -1) {
229 return RET_ERR("%s", g_strerror(errno));
230 }
231 g_close(fd, NULL);
232
233 return SRN_OK;
234 }
235