Split required functions for public
[platform/core/system/tizen-platform-config.git] / src / shared-api.c
1 /*
2  * Copyright (C) 2013-2014 Intel Corporation.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors:
19  *       José Bollo <jose.bollo@open.eurogiciel.org>
20  *       Stéphane Desneux <stephane.desneux@open.eurogiciel.org>
21  *       Jean-Benoit Martin <jean-benoit.martin@open.eurogiciel.org>
22  *
23  */
24 #define _GNU_SOURCE
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <assert.h>
34 #include <syslog.h>
35
36 #ifndef NOT_MULTI_THREAD_SAFE
37 #include <pthread.h>
38 #endif
39
40 #include "tzplatform_variables.h"
41 #include "tzplatform_config.h"
42 #include "heap.h"
43 #include "scratch.h"
44 #include "passwd.h"
45 #include "context.h"
46 #include "hashing.h"
47 #include "init.h"
48 #include "shared-api.h"
49
50 /* the global context */
51 static struct tzplatform_context global_context = {
52 #ifndef NOT_MULTI_THREAD_SAFE
53         .mutex = PTHREAD_MUTEX_INITIALIZER,
54 #endif
55         .state = RESET,
56         .user = _USER_NOT_SET_
57 };
58
59 /* the signup of names */
60 #include "signup.inc"
61
62 /* validate the signup */
63 static void validate_signup(char signup[33])
64 {
65         if (memcmp(signup+1, tizen_platform_config_signup+1, 32)) {
66                 syslog(LOG_CRIT, "Bad signup of the client of tizen-platform-config");
67                 abort();
68         }
69         signup[0] = 1;
70 }
71
72 /* check the signup */
73 static inline void check_signup(char signup[33])
74 {
75         if (!signup[0])
76                 validate_signup(signup);
77 }
78
79 /* locks the context */
80 static inline void lock(struct tzplatform_context *context)
81 {
82 #ifndef NOT_MULTI_THREAD_SAFE
83         pthread_mutex_lock(&context->mutex);
84 #endif
85 }
86
87 /* unlock the context */
88 static inline void unlock(struct tzplatform_context *context)
89 {
90 #ifndef NOT_MULTI_THREAD_SAFE
91         pthread_mutex_unlock(&context->mutex);
92 #endif
93 }
94
95 static inline const char *get_lock(int id, struct tzplatform_context *context)
96 {
97         lock(context);
98
99         if (id < 0 || (int)_TZPLATFORM_VARIABLES_COUNT_ <= id)
100                 return NULL;
101
102         if (context->state == RESET)
103                 initialize(context);
104
105         return context->state == ERROR ? NULL : context->values[id];
106 }
107
108 /*************** PUBLIC API begins here **************/
109
110 int tzplatform_context_create(struct tzplatform_context **result)
111 {
112         struct tzplatform_context *context;
113
114         context = malloc(sizeof * context);
115         *result = context;
116         if (context == NULL)
117                 return -1;
118
119         context->state = RESET;
120         context->user = _USER_NOT_SET_;
121 #ifndef NOT_MULTI_THREAD_SAFE
122         pthread_mutex_init(&context->mutex, NULL);
123 #endif
124         return 0;
125 }
126
127 void tzplatform_context_destroy(struct tzplatform_context *context)
128 {
129         if (context->state == VALID)
130                         heap_destroy(&context->heap);
131         context->state = ERROR;
132         free(context);
133 }
134
135 void tzplatform_reset()
136 {
137         tzplatform_context_reset(&global_context);
138 }
139
140 void tzplatform_context_reset(struct tzplatform_context *context)
141 {
142         lock(context);
143         if (context->state != RESET) {
144                 if (context->state == VALID)
145                         heap_destroy(&context->heap);
146                 context->state = RESET;
147         }
148         unlock(context);
149 }
150
151 uid_t tzplatform_get_user(char signup[33])
152 {
153         return tzplatform_context_get_user(&global_context);
154 }
155
156 uid_t tzplatform_context_get_user(struct tzplatform_context *context)
157 {
158         uid_t result;
159
160         lock(context);
161         result = get_uid(context);
162         unlock(context);
163
164         return result;
165 }
166
167 void tzplatform_reset_user()
168 {
169         tzplatform_context_reset_user(&global_context);
170 }
171
172 void tzplatform_context_reset_user(struct tzplatform_context *context)
173 {
174         tzplatform_context_set_user(context, _USER_NOT_SET_);
175 }
176
177 int tzplatform_set_user(uid_t uid)
178 {
179         return tzplatform_context_set_user(&global_context, uid);
180 }
181
182 int tzplatform_context_set_user(struct tzplatform_context *context, uid_t uid)
183 {
184         lock(context);
185         if (context->user != uid) {
186                 if (uid != _USER_NOT_SET_ && !pw_has_uid(context, uid)) {
187                         unlock(context);
188                         return -1;
189         }
190                 else {
191                         if (context->state == VALID)
192                                 heap_destroy(&context->heap);
193                         context->state = RESET;
194                         context->user = uid;
195                 }
196         }
197         unlock(context);
198
199         return 0;
200 }
201
202 /*************** PUBLIC INTERNAL API begins here **************/
203
204 const char* _getname_tzplatform_(int id, char signup[33])
205 {
206         check_signup(signup);
207         return 0 <= id && id < _TZPLATFORM_VARIABLES_COUNT_ ? keyname(id) : NULL;
208 }
209
210 int _getid_tzplatform_(const char *name, char signup[33])
211 {
212         check_signup(signup);
213         return hashid(name, strlen(name));
214 }
215
216 const char* _getenv_tzplatform_(int id, char signup[33])
217 {
218         return _context_getenv_tzplatform_(id, signup, &global_context);
219 }
220
221 const char* _context_getenv_tzplatform_(int id, char signup[33], struct tzplatform_context *context)
222 {
223         const char *array[2];
224         const char *result;
225
226         check_signup(signup);
227         result = get_lock(id, context);
228         if (result != NULL) {
229                 array[0] = result;
230                 array[1] = NULL;
231                 result = scratchcat(0, array);
232         }
233         unlock(context);
234         return result;
235 }
236
237 int _getenv_int_tzplatform_(int id, char signup[33])
238 {
239         return _context_getenv_int_tzplatform_(id, signup, &global_context);
240 }
241
242 int _context_getenv_int_tzplatform_(int id, char signup[33], struct tzplatform_context *context)
243 {
244         const char *value;
245         int result;
246
247         check_signup(signup);
248         value = get_lock(id, context);
249         result = (value == NULL) ? -1 : atoi(value);
250         unlock(context);
251         return result;
252 }
253
254 const char* _mkstr_tzplatform_(int id, const char * str, char signup[33])
255 {
256         return _context_mkstr_tzplatform_(id, str, signup,      &global_context);
257 }
258
259 const char* _context_mkstr_tzplatform_(int id, const char *str, char signup[33], struct tzplatform_context *context)
260 {
261         const char *array[3];
262         const char *result;
263
264         check_signup(signup);
265         result = get_lock(id, context);
266         if (result != NULL) {
267                 array[0] = result;
268                 array[1] = str;
269                 array[2] = NULL;
270                 result = scratchcat(0, array);
271         }
272         unlock(context);
273         return result;
274 }
275
276 const char* _mkpath_tzplatform_(int id, const char * path, char signup[33])
277 {
278         return _context_mkpath_tzplatform_(id, path, signup,  &global_context);
279 }
280
281 const char* _context_mkpath_tzplatform_(int id, const char *path, char signup[33], struct tzplatform_context *context)
282 {
283         const char *array[3];
284         const char *result;
285
286         check_signup(signup);
287         result = get_lock(id, context);
288         if (result != NULL) {
289                 array[0] = result;
290                 array[1] = path;
291                 array[2] = NULL;
292                 result = scratchcat(1, array);
293         }
294         unlock(context);
295         return result;
296 }
297
298 const char* _mkpath3_tzplatform_(int id, const char * path, const char* path2, char signup[33])
299 {
300         return _context_mkpath3_tzplatform_(id, path, path2, signup,  &global_context);
301 }
302
303 const char* _context_mkpath3_tzplatform_(int id, const char *path, const char *path2, char signup[33], struct tzplatform_context *context)
304 {
305         const char *array[4];
306         const char *result;
307
308         check_signup(signup);
309         result = get_lock(id, context);
310         if (result != NULL) {
311                 array[0] = result;
312                 array[1] = path;
313                 array[2] = path2;
314                 array[3] = NULL;
315                 result = scratchcat(1, array);
316         }
317         unlock(context);
318         return result;
319 }
320
321 const char* _mkpath4_tzplatform_(int id, const char * path, const char* path2, const char *path3, char signup[33])
322 {
323         return _context_mkpath4_tzplatform_(id, path, path2, path3, signup,  &global_context);
324 }
325
326 const char* _context_mkpath4_tzplatform_(int id, const char *path, const char *path2, const char *path3, char signup[33], struct tzplatform_context *context)
327 {
328         const char *array[5];
329         const char *result;
330
331         check_signup(signup);
332         result = get_lock(id, context);
333         if (result != NULL) {
334                 array[0] = result;
335                 array[1] = path;
336                 array[2] = path2;
337                 array[3] = path3;
338                 array[4] = NULL;
339                 result = scratchcat(1, array);
340         }
341         unlock(context);
342         return result;
343 }
344
345 uid_t _getuid_tzplatform_(int id, char signup[33])
346 {
347         return _context_getuid_tzplatform_(id, signup,  &global_context);
348 }
349
350 uid_t _context_getuid_tzplatform_(int id, char signup[33], struct tzplatform_context *context)
351 {
352         uid_t result;
353         const char *value;
354
355         check_signup(signup);
356         result = (uid_t)-1;
357         value = get_lock(id, context);
358         if (value != NULL)
359                 pw_get_uid(context, value, &result);
360
361         unlock(context);
362         return result;
363 }
364
365 gid_t _getgid_tzplatform_(int id, char signup[33])
366 {
367         return _context_getgid_tzplatform_(id, signup,  &global_context);
368 }
369
370 gid_t _context_getgid_tzplatform_(int id, char signup[33], struct tzplatform_context *context)
371 {
372         gid_t result;
373         const char *value;
374
375         check_signup(signup);
376         result = (uid_t)-1;
377         value = get_lock(id, context);
378         if (value != NULL)
379                 pw_get_gid(context, value, &result);
380
381         unlock(context);
382         return result;
383 }
384