ini: first implementation
[platform/core/uifw/libtdm.git] / src / tdm_config.c
1 /**************************************************************************
2  *
3  * libtdm
4  *
5  * Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6  *
7  * Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8  *          JinYoung Jeon <jy0.jeon@samsung.com>,
9  *          Taeheon Kim <th908.kim@samsung.com>,
10  *          YoungJun Cho <yj44.cho@samsung.com>,
11  *          SooChan Lim <sc1.lim@samsung.com>,
12  *          Boram Park <sc1.lim@samsung.com>
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a
15  * copy of this software and associated documentation files (the
16  * "Software"), to deal in the Software without restriction, including
17  * without limitation the rights to use, copy, modify, merge, publish,
18  * distribute, sub license, and/or sell copies of the Software, and to
19  * permit persons to whom the Software is furnished to do so, subject to
20  * the following conditions:
21  *
22  * The above copyright notice and this permission notice (including the
23  * next paragraph) shall be included in all copies or substantial portions
24  * of the Software.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29  * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33  *
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include <iniparser.h>
41
42 #include "tdm_log.h"
43 #include "tdm_macro.h"
44 #include "tdm_list.h"
45 #include "tdm.h"
46 #include "tdm_private.h"
47 #include "tdm_config.h"
48
49 #define TDM_CONFIG_FILENAME "tdm.ini"
50 #define TDM_CONFIG_GENERAL_SECTION "general"
51
52 static dictionary *g_dic = NULL;
53 static pthread_mutex_t g_dic_lock;
54
55 static int
56 _tdm_config_check_file_owner(const char *filepath)
57 {
58         struct stat sb;
59
60         if (stat(filepath, &sb) < 0) {
61                 TDM_WRN("%s: %m", filepath);
62                 return -1;
63         }
64
65         if (sb.st_uid != getuid()) {
66                 TDM_WRN("'%s': not owned by %u", filepath, getuid());
67                 return -1;
68         }
69
70         return 0;
71 }
72
73 static dictionary *
74 _tdm_config_load_file(const char *dir, const char *filename)
75 {
76         char filepath[TDM_PATH_LEN];
77         dictionary *dic;
78
79         snprintf(filepath, sizeof filepath, "%s/%s", dir, filename);
80
81         if (_tdm_config_check_file_owner(filepath) < 0)
82                 return NULL;
83
84         dic = iniparser_load(filepath);
85         TDM_RETURN_VAL_IF_FAIL(dic != NULL, NULL);
86
87         if (!iniparser_find_entry(dic, TDM_CONFIG_GENERAL_SECTION)) {
88                 TDM_ERR("no '%s' section: '%s'", TDM_CONFIG_GENERAL_SECTION, filepath);
89                 iniparser_freedict(dic);
90                 return NULL;
91         }
92
93         TDM_INFO("opened successed: '%s'", filepath);
94
95         return dic;
96 }
97
98 static dictionary *
99 _tdm_config_load(void)
100 {
101         dictionary *dic = NULL;
102
103 #if 0
104         /* not allowed: try to read from RW directory */
105         dic = _tdm_config_load_file(TDM_SYSCONF_PATH, TDM_CONFIG_FILENAME);
106 #endif
107
108         if (!dic) {
109                 /* try to read from RO directory */
110                 dic = _tdm_config_load_file(TDM_DATA_PATH, TDM_CONFIG_FILENAME);
111         }
112
113         return dic;
114 }
115
116 INTERN tdm_error
117 tdm_config_init(void)
118 {
119         if (g_dic) {
120                 TDM_ERR("init failed: twice");
121                 return TDM_ERROR_OPERATION_FAILED;
122         }
123
124         if (pthread_mutex_init(&g_dic_lock, NULL)) {
125                 TDM_ERR("mutex init failed: %m");
126                 return TDM_ERROR_OUT_OF_MEMORY;
127         }
128
129         g_dic = _tdm_config_load();
130         if (!g_dic) {
131                 if (!getenv("TDM_NO_CONFIG")) {
132                         TDM_ERR("Loading config file failed!!");
133                         pthread_mutex_destroy(&g_dic_lock);
134                         return TDM_ERROR_NONE;
135                 }
136         }
137
138         TDM_INFO("tdm config init done (%p)", g_dic);
139
140         return TDM_ERROR_NONE;
141 }
142
143 INTERN void
144 tdm_config_deinit(void)
145 {
146         if (!g_dic) {
147                 return;
148         }
149
150         iniparser_freedict(g_dic);
151         g_dic = NULL;
152
153         /* we don't need to lock/unlock here because we come here
154          * after tdm_thread has been destroyed
155          */
156         pthread_mutex_destroy(&g_dic_lock);
157
158         TDM_INFO("tdm config deinit done");
159 }
160
161 static const char*
162 _tdm_config_get_string_internal(dictionary *dic, const char *key, const char *default_value)
163 {
164         char *temp = NULL;
165         const char *result;
166
167         if (default_value) {
168                 temp = strdup(default_value);
169                 if (!temp) {
170                         TDM_ERR("strdup failed: %m");
171                         return default_value;
172                 }
173         }
174
175         result = (const char *)iniparser_getstring(dic, key, temp);
176         if (!result || strlen(result) == 0) {
177                 free(temp);
178                 return default_value;
179         }
180
181         free(temp);
182
183         return result;
184 }
185
186 INTERN int
187 tdm_config_get_int(const char *key, int default_value)
188 {
189         const char *result;
190         int value;
191
192         TDM_RETURN_VAL_IF_FAIL(key != NULL, default_value);
193
194         if (!g_dic) {
195                 TDM_INFO("%s = %d: default", key, default_value);
196                 return default_value;
197         }
198
199         pthread_mutex_lock(&g_dic_lock);
200         result = _tdm_config_get_string_internal(g_dic, key, NULL);
201         pthread_mutex_unlock(&g_dic_lock);
202
203         if (!result) {
204                 TDM_INFO("%s = %d: no key", key, default_value);
205                 return default_value;
206         }
207
208         value = (int)strtol(result, NULL, 0);
209
210         TDM_INFO("%s = %d", key, value);
211
212         return value;
213 }
214
215 INTERN const char*
216 tdm_config_get_string(const char *key, const char *default_value)
217 {
218         const char *result;
219
220         TDM_RETURN_VAL_IF_FAIL(key != NULL, default_value);
221
222         if (!g_dic) {
223                 TDM_INFO("%s = %s: default", key, default_value);
224                 return default_value;
225         }
226
227         pthread_mutex_lock(&g_dic_lock);
228         result = _tdm_config_get_string_internal(g_dic, key, default_value);
229         pthread_mutex_unlock(&g_dic_lock);
230
231         TDM_INFO("%s = %s", key, result);
232
233         return result;
234 }
235
236 INTERN tdm_error
237 tdm_config_set_int(const char *key, int value)
238 {
239         char temp[TDM_NAME_LEN];
240         int ret;
241
242         TDM_RETURN_VAL_IF_FAIL(key != NULL, TDM_ERROR_INVALID_PARAMETER);
243
244         if (!g_dic) {
245                 TDM_INFO("%s = %d set failed", key, value);
246                 return TDM_ERROR_BAD_REQUEST;
247         }
248
249         snprintf(temp, sizeof temp, "%d", value);
250
251         pthread_mutex_lock(&g_dic_lock);
252         ret = iniparser_set(g_dic, key, (const char*)temp);
253         pthread_mutex_unlock(&g_dic_lock);
254
255         TDM_RETURN_VAL_IF_FAIL(ret == 0, TDM_ERROR_OPERATION_FAILED);
256
257         TDM_INFO("%s = %d set done", key, value);
258
259         return TDM_ERROR_NONE;
260 }
261
262 INTERN tdm_error
263 tdm_config_set_string(const char *key, const char *value)
264 {
265         int ret;
266
267         TDM_RETURN_VAL_IF_FAIL(key != NULL, TDM_ERROR_INVALID_PARAMETER);
268
269         if (!g_dic) {
270                 TDM_INFO("%s = %s set failed", key, value);
271                 return TDM_ERROR_BAD_REQUEST;
272         }
273
274         pthread_mutex_lock(&g_dic_lock);
275         ret = iniparser_set(g_dic, key, value);
276         pthread_mutex_unlock(&g_dic_lock);
277
278         TDM_RETURN_VAL_IF_FAIL(ret == 0, TDM_ERROR_OPERATION_FAILED);
279
280         TDM_INFO("%s = %s set done", key, value);
281
282         return TDM_ERROR_NONE;
283 }