2 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
3 * Copyright (C) 2014 Intel Corporation
5 * Author: José Bollo <jose.bollo@open.eurogiciel.org>
6 * Author: Hakjoo Ko <hakjoo.ko@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 * Note on conditionnal compilation: The following defines are controlling the compilation.
26 * Defining NO_MULTITHREADING removes multithreading support.
27 * Defining it is not a good idea.
30 * Defining NO_GLIB removes support of GLIB main loop used for notification
31 * Defining it implies to dig code to find some replacement (new API verbs to create).
34 * Removes the prefixe of the keys depending (depends on the layer).
35 * Defining it is not a good idea.
37 * The best is to not define any of the conditional value and let use the default.
53 #if !defined(NO_MULTITHREADING)
57 #include "vconf-buxton.h"
60 /*================= SECTION definition of types =============*/
63 * internal types for keys
67 type_unset, /* type unset or unknown */
68 type_directory, /* a directory, not a real key */
69 type_delete, /* key to be deleted */
70 type_string, /* key of type string */
71 type_int, /* key of type integer */
72 type_double, /* key of type double */
73 type_bool /* key of type boolean */
77 * union for storing values
81 int i; /* storage of integers */
82 int b; /* storage of booleans */
83 double d; /* storage of doubles */
84 char *s; /* storage of strings */
92 enum keytype type; /* type of the key */
93 union keyvalue value; /* value of the key */
94 keynode_t *next; /* linking to the next key */
95 keylist_t *list; /* the containing list */
96 const char *keyname; /* name of the key */
100 * structure for list of keys
104 int num; /* count of keys in the list */
105 keynode_t *head; /* first key of the list */
106 keynode_t *cursor; /* iterator on keys for clients */
107 int cb_active; /* callback global activity */
108 int cb_status; /* callback global status */
109 unsigned cb_sent; /* callback global count of sent queries */
110 unsigned cb_received; /* callback global count of
111 * received responses */
115 * data for the callback of scanning
119 int pending; /* is the scan pending? */
120 int cb_status; /* status of the call back */
121 int want_directories; /* is scanning directories? */
122 int want_keys; /* is scanning keys? */
123 int is_recursive; /* is scanning recursively? */
124 size_t dirlen; /* length of the directory */
125 keylist_t *keylist; /* keylist to fill */
126 const char *prefix; /* prefix to add in front of names */
127 const char *directory; /* scanned directory */
131 * data when translating vconf names to buxton names. ** the rule is that
136 const char *layer; /* identified layer-name */
137 const char *prefix; /* vconf prefix of the name (without
139 const char *key; /* buxton key-name (without leading /) */
143 * singleton data for facilities
147 keylist_t list; /* the list */
148 keynode_t node; /* its single node */
152 * structure for notifications
156 int status; /* callback status */
157 vconf_callback_fn callback; /* the user callback */
158 void *userdata; /* the user data */
159 keynode_t *keynode; /* the recorded key node */
160 struct notify *next; /* tink to the next notification */
163 /*================= SECTION local variables =============*/
166 * maximum length of key-names
168 static size_t keyname_maximum_length = 2030;
171 * maximum length of group-names
173 static size_t keygroup_maximum_length = 1010;
176 * association from prefixes to layers
178 static const char *assoc_prefix_layer[][2] = {
182 {"memory_init", "base"},
188 * default timeout in scanning responses
190 static int default_timeout = 5000; /* in milliseconds */
193 * instance of the buxton client
195 static BuxtonClient the_buxton_client = 0;
198 * the file handle number for polling buxton events
200 static int the_buxton_client_fd = 0;
203 * flag indacating if the buxton client is set or not
205 static char the_buxton_client_is_set = 0;
208 * the group to use if default group is unset
210 static const char initial_default_group[] = "vconf";
213 * the default group to use
215 static char *default_group = NULL;
220 static keylist_t *notify_keylist = NULL;
225 static struct notify *notify_entries = NULL;
230 static int internal_list_count = 0;
232 #if !defined(NO_GLIB)
234 * link to the glib main loop
236 static GSource *glib_source = NULL;
240 * error code for vconf_get_ext_errno()
242 static int g_vconf_errno = 0;
244 #if !defined(NO_MULTITHREADING)
246 * multithreaded protection
247 * CAUTION: always use the given order!
249 static pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER;
250 static pthread_mutex_t mutex_counter = PTHREAD_MUTEX_INITIALIZER;
251 static pthread_mutex_t mutex_buxton = PTHREAD_MUTEX_INITIALIZER;
252 static pthread_mutex_t mutex_group = PTHREAD_MUTEX_INITIALIZER;
253 #define LOCK(x) pthread_mutex_lock(&mutex_##x)
254 #define UNLOCK(x) pthread_mutex_unlock(&mutex_##x)
260 /*================= SECTION utils =============*/
263 * duplication of a string with validation of the length
266 _dup_ (const char *source, size_t maxlen, const char *tag)
271 assert (source != NULL);
272 length = strlen (source);
273 if (length >= maxlen)
275 ERR ("Invalid argument: %s is too long", tag);
278 result = malloc (++length);
281 ERR ("Can't allocate memory for %s", tag);
284 memcpy (result, source, length);
288 /*================= SECTION groupname utils =============*/
291 _dup_groupname_ (const char *groupname)
293 return _dup_ (groupname, keygroup_maximum_length, "group-name");
297 _ensure_default_group_ ()
299 int result = VCONF_OK;
302 if (default_group == NULL)
304 default_group = _dup_groupname_ (initial_default_group);
305 if (default_group == NULL)
306 result = VCONF_ERROR;
313 /*================= SECTION key utils =============*/
316 _keynode_free_ (keynode_t * keynode)
318 assert (keynode != NULL);
319 if (keynode->type == type_string)
320 free (keynode->value.s);
325 _check_keyname_ (const char *keyname)
329 assert (keyname != NULL);
336 for (result = 0; keyname[result]; result++)
338 if (keyname[result] == '/' && keyname[result + 1] == '/')
347 /*================= SECTION list utils =============*/
350 * search in 'keylist' an entry of 'keyname' and return it if found or
351 * NULL if not found. 'previous' if not NULL and if the entry is found
352 * will recieve the address of the pointer referencing the returned node.
354 static inline keynode_t *
355 _keylist_lookup_ (keylist_t * keylist,
356 const char *keyname, keynode_t *** previous)
358 keynode_t *node, **prev;
359 size_t length = 1 + strlen (keyname);
361 prev = &keylist->head;
362 node = keylist->head;
365 assert (node->keyname != NULL);
366 if (!memcmp (keyname, node->keyname, length))
379 static inline keynode_t *
380 _keylist_add_ (keylist_t * keylist, const char *keyname, enum keytype type)
387 * not found, create it
389 length = _check_keyname_ (keyname);
390 retvm_if (!length, NULL, "invalid keyname");
391 retvm_if (length > keyname_maximum_length, NULL, "keyname too long");
392 result = malloc (1 + length + sizeof *result);
393 retvm_if (result == NULL, NULL, "allocation of keynode failed");
395 result->value.s = NULL;
397 result->list = keylist;
398 name = (char *) (result + 1);
399 result->keyname = name;
400 memcpy (name, keyname, length + 1);
402 result->next = keylist->head;
403 keylist->head = result;
409 static inline keynode_t *
410 _keylist_getadd_ (keylist_t * keylist, const char *keyname, enum keytype type)
415 * search keynode of keyname
417 result = _keylist_lookup_ (keylist, keyname, NULL);
421 * not found, create it
423 result = _keylist_add_ (keylist, keyname, type);
425 else if (result->type != type)
427 if (result->type == type_string)
428 free (result->value.s);
430 result->value.s = NULL;
436 _keylist_init_singleton_ (struct singleton *singleton, const char *keyname,
441 if (!_check_keyname_ (keyname))
443 ERR ("Invalid key name(%s)", keyname);
446 status = _ensure_default_group_ ();
447 if (status != VCONF_OK)
450 memset (singleton, 0, sizeof *singleton);
451 singleton->list.num = 1;
452 singleton->list.head = &singleton->node;
453 singleton->node.keyname = keyname;
454 singleton->node.type = type;
455 singleton->node.list = &singleton->list;
461 /*================= SECTION buxton =============*/
464 _check_close_buxton_ ()
470 if (internal_list_count == 0 && notify_entries == NULL)
471 if (internal_list_count == 0 && notify_entries == NULL)
474 bc = the_buxton_client;
475 the_buxton_client_is_set = 0;
476 the_buxton_client = NULL;
477 the_buxton_client_fd = -1;
487 _try_to_open_buxton_ ()
489 the_buxton_client_fd = buxton_open (&the_buxton_client);
490 if (the_buxton_client_fd < 0)
492 ERR ("can't connect to buxton server: %m");
494 the_buxton_client = NULL;
502 if (!the_buxton_client_is_set)
505 * first time, try to connect to buxton
507 the_buxton_client_is_set = 1;
508 _try_to_open_buxton_ ();
511 return the_buxton_client != NULL;
515 static inline BuxtonClient
518 BuxtonClient result = the_buxton_client;
519 assert (result != NULL);
524 _handle_buxton_response_ (int lock)
530 result = buxton_client_handle_response (_buxton_ ());
532 ERR ("Error in buxton_client_handle_response: %m");
534 ERR ("Connection closed");
543 _dispatch_buxton_ (int writing, int lock)
548 assert (_buxton_ () != NULL);
550 pfd.fd = the_buxton_client_fd;
551 pfd.events = writing ? POLLIN | POLLOUT : POLLIN;
555 status = poll (&pfd, 1, default_timeout);
563 else if (status == 1)
565 if (pfd.revents & POLLIN)
567 status = _handle_buxton_response_ (lock);
577 if (pfd.revents & POLLOUT)
590 _wait_buxton_response_ (int *pending)
596 result = _dispatch_buxton_ (0, 1);
598 while (result == VCONF_OK && *pending);
603 _get_layer_key_ (const char *keyname, struct layer_key *laykey)
612 prefix = assoc_prefix_layer[i][0];
613 while (prefix != NULL)
615 for (j = 0; prefix[j] && prefix[j] == keyname[j]; j++);
616 if (!prefix[j] && (!keyname[j] || keyname[j] == '/'))
618 laykey->prefix = prefix;
619 laykey->layer = assoc_prefix_layer[i][1];
620 #if defined(REMOVE_PREFIXES)
621 laykey->key = keyname + j + (keyname[j] == '/');
623 laykey->key = keyname;
628 prefix = assoc_prefix_layer[i][0];
630 ERR ("Invalid argument: wrong prefix of key(%s)", keyname);
634 static inline BuxtonKey
635 _get_buxton_key_ (keynode_t * node)
638 struct layer_key laykey;
643 if (_get_layer_key_ (node->keyname, &laykey) != VCONF_OK)
654 type = BUXTON_TYPE_STRING;
657 type = BUXTON_TYPE_INT32;
660 type = BUXTON_TYPE_DOUBLE;
663 type = BUXTON_TYPE_BOOLEAN;
666 type = BUXTON_TYPE_UNSET;
669 return buxton_key_create (default_group, laykey.key, laykey.layer, type);
672 /*================= SECTION set/unset/refresh =============*/
675 _cb_inc_received_ (BuxtonResponse resp, keynode_t * keynode)
679 assert (keynode != NULL);
680 assert (keynode->list != NULL);
682 list = keynode->list;
684 if ((g_vconf_errno = buxton_response_status (resp)) != 0)
686 ERR ("Buxton returned error %d for key %s",
687 buxton_response_status (resp), keynode->keyname);
688 list->cb_status = VCONF_ERROR;
693 _set_response_to_keynode_ (BuxtonResponse resp, keynode_t * keynode,
697 BuxtonDataType buxtyp;
700 assert (keynode != NULL);
701 assert (buxton_response_status (resp) == 0);
703 buxtyp = buxton_response_value_type (resp);
706 case BUXTON_TYPE_STRING:
709 case BUXTON_TYPE_INT32:
712 case BUXTON_TYPE_DOUBLE:
715 case BUXTON_TYPE_BOOLEAN:
722 if (force && type != keynode->type && keynode->type != type_unset)
725 buxval = buxton_response_value (resp);
729 if (keynode->type == type_string)
730 free (keynode->value.s);
732 keynode->type = type;
736 keynode->value.s = buxval;
739 keynode->value.i = (int) *(int32_t *) buxval;
742 keynode->value.d = *(double *) buxval;
745 keynode->value.b = *(bool *) buxval;
756 _cb_refresh_ (BuxtonResponse resp, keynode_t * keynode)
760 assert (keynode != NULL);
761 assert (keynode->list != NULL);
762 assert (buxton_response_type (resp) == BUXTON_CONTROL_GET);
764 list = keynode->list;
766 if ((g_vconf_errno = buxton_response_status (resp)) != 0)
768 ERR ("Error %d while getting buxton key %s",
769 buxton_response_status (resp), keynode->keyname);
770 list->cb_status = VCONF_ERROR;
772 else if (_set_response_to_keynode_ (resp, keynode, 0) != VCONF_OK)
774 list->cb_status = VCONF_ERROR;
779 _cb_scan_ (BuxtonResponse resp, struct scanning_data *data)
793 * check the response status
795 if ((g_vconf_errno = buxton_response_status (resp)) != 0)
797 ERR ("Error while getting list of names from buxton");
798 data->cb_status = VCONF_ERROR;
803 * iterate on the list of names
805 assert (data->directory[data->dirlen - 1] == '/');
806 keylist = data->keylist;
807 count = buxton_response_list_names_count (resp);
809 while (index < count)
814 buxname = buxton_response_list_names_item (resp, index++);
817 ERR ("Unexpected NULL name returned by buxton");
818 data->cb_status = VCONF_ERROR;
825 #if defined(REMOVE_PREFIXES)
826 length = asprintf (&name, "%s/%s", data->prefix, buxname);
828 length = asprintf (&name, "%s", buxname);
833 ERR ("Memory allocation error");
834 data->cb_status = VCONF_ERROR;
837 assert (_check_keyname_ (name));
838 assert (!memcmp (data->directory, name, data->dirlen));
841 * add key if requested
843 term = strchr (name + data->dirlen, '/');
844 if (data->want_keys && (data->is_recursive || term == NULL))
846 keynode = _keylist_getadd_ (keylist, name, type_unset);
850 data->cb_status = VCONF_ERROR;
856 * add directories if requested
858 if (data->want_directories)
863 keynode = _keylist_getadd_ (keylist, name, type_directory);
867 data->cb_status = VCONF_ERROR;
870 if (!data->is_recursive)
875 term = strchr (term + 1, '/');
881 data->cb_status = VCONF_OK;
886 _async_set_ (keynode_t * keynode)
892 assert (keynode != NULL);
894 switch (keynode->type)
897 data = keynode->value.s;
902 data = &keynode->value;
908 key = _get_buxton_key_ (keynode);
914 status = buxton_set_value (_buxton_ (), key,
916 (BuxtonCallback) _cb_inc_received_, keynode,
918 buxton_key_free (key);
925 ERR ("Error while calling buxton_set_value: %m");
930 _async_unset_ (keynode_t * keynode)
935 assert (keynode != NULL);
937 if (keynode->type != type_delete)
942 key = _get_buxton_key_ (keynode);
948 status = buxton_unset_value (_buxton_ (), key,
949 (BuxtonCallback) _cb_inc_received_,
951 buxton_key_free (key);
958 ERR ("Error while calling buxton_unset_value: %m");
963 _async_set_or_unset_ (keynode_t * keynode, const char *unused)
965 assert (keynode != NULL);
967 switch (keynode->type)
973 return _async_unset_ (keynode);
975 return _async_set_ (keynode);
980 _async_refresh_ (keynode_t * keynode, const char *unused)
985 assert (keynode != NULL);
987 switch (keynode->type)
999 key = _get_buxton_key_ (keynode);
1005 status = buxton_get_value (_buxton_ (), key,
1006 (BuxtonCallback) _cb_refresh_, keynode, false);
1007 buxton_key_free (key);
1014 ERR ("Error while calling buxton_get_value: %m");
1019 _async_set_label_ (keynode_t * keynode, const char *label)
1024 assert (keynode != NULL);
1026 key = _get_buxton_key_ (keynode);
1032 status = buxton_set_label (_buxton_ (), key, label,
1033 (BuxtonCallback) _cb_inc_received_,
1035 buxton_key_free (key);
1042 ERR ("Error while calling buxton_set_label: %m");
1048 _apply_buxton_on_list_ (keylist_t * keylist,
1049 int (*async) (keynode_t *, const char *),
1056 assert (keylist != NULL);
1058 status = _open_buxton_ ();
1059 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1060 assert (_buxton_ () != NULL);
1062 retvm_if (keylist->cb_active != 0, VCONF_ERROR,
1063 "Already active in vconf-buxton");
1067 keylist->cb_active = 1;
1068 keylist->cb_status = VCONF_OK;
1069 keylist->cb_sent = 0;
1070 keylist->cb_received = 0;
1072 keynode = keylist->head;
1073 status = _dispatch_buxton_ (1, 0);
1074 while (keynode != NULL && status == VCONF_OK)
1076 sent = async (keynode, data);
1077 keynode = keynode->next;
1080 status = VCONF_ERROR;
1084 keylist->cb_sent += sent;
1085 status = _dispatch_buxton_ (1, 0);
1092 while (status == VCONF_OK && keylist->cb_sent != keylist->cb_received)
1094 status = _dispatch_buxton_ (0, 0);
1097 if (status == VCONF_OK && keylist->cb_status != VCONF_OK)
1098 status = keylist->cb_status;
1099 keylist->cb_active = 0;
1103 _check_close_buxton_ ();
1108 /*================= SECTION notification =============*/
1111 _cb_notify_ (BuxtonResponse resp, struct notify *notif)
1113 switch (buxton_response_type (resp))
1115 case BUXTON_CONTROL_NOTIFY:
1116 case BUXTON_CONTROL_UNNOTIFY:
1118 buxton_response_status (resp) == 0 ? VCONF_OK : VCONF_ERROR;
1120 case BUXTON_CONTROL_CHANGED:
1121 if (_set_response_to_keynode_ (resp, notif->keynode, 1) == VCONF_OK)
1124 notif->callback (notif->keynode, notif->userdata);
1134 _notify_reg_unreg_ (struct notify *notif, bool reg)
1139 status = _open_buxton_ ();
1140 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1143 key = _get_buxton_key_ (notif->keynode);
1144 retvm_if (key == NULL, VCONF_ERROR, "Can't create buxton key");
1145 notif->status = VCONF_OK; /* on success calback isn't called! */
1147 (reg ? buxton_register_notification :
1148 buxton_unregister_notification) (_buxton_ (), key,
1149 (BuxtonCallback) _cb_notify_,
1151 buxton_key_free (key);
1153 return status == 0 && notif->status == VCONF_OK ? VCONF_OK : VCONF_ERROR;
1156 #if !defined(NO_GLIB)
1157 /*================= SECTION glib =============*/
1160 _cb_glib_ (GIOChannel * src, GIOCondition cond, gpointer data)
1164 status = _handle_buxton_response_ (1);
1167 return G_SOURCE_REMOVE;
1169 return G_SOURCE_CONTINUE;
1173 _glib_start_watch_ ()
1177 if (glib_source != NULL)
1180 gio = g_io_channel_unix_new (the_buxton_client_fd);
1181 retvm_if (gio == NULL, VCONF_ERROR, "Error: create a new GIOChannel");
1183 g_io_channel_set_flags (gio, G_IO_FLAG_NONBLOCK, NULL);
1185 glib_source = g_io_create_watch (gio, G_IO_IN);
1186 if (glib_source == NULL)
1188 ERR ("Error: create a new GSource");
1189 g_io_channel_unref (gio);
1193 g_source_set_callback (glib_source, (GSourceFunc) _cb_glib_, NULL, NULL);
1194 g_source_attach (glib_source, NULL);
1195 g_io_channel_unref (gio);
1196 g_source_unref (glib_source);
1202 _glib_stop_watch_ ()
1204 if (glib_source != NULL)
1206 g_source_destroy (glib_source);
1212 /*================= SECTION VCONF API =============*/
1215 vconf_keynode_get_name (keynode_t * keynode)
1217 retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL");
1218 retvm_if (keynode->keyname == NULL, NULL, "The name of keynode is NULL");
1220 return keynode->keyname;
1224 vconf_keynode_get_type (keynode_t * keynode)
1226 retvm_if (keynode == NULL,
1227 VCONF_ERROR, "Invalid argument: keynode is NULL");
1229 switch (keynode->type)
1231 case type_directory:
1232 return VCONF_TYPE_DIR;
1234 return VCONF_TYPE_STRING;
1236 return VCONF_TYPE_INT;
1238 return VCONF_TYPE_DOUBLE;
1240 return VCONF_TYPE_BOOL;
1242 return VCONF_TYPE_NONE;
1247 vconf_keynode_get_int (keynode_t * keynode)
1249 retvm_if (keynode == NULL,
1250 VCONF_ERROR, "Invalid argument: keynode is NULL");
1251 retvm_if (keynode->type != type_int, VCONF_ERROR,
1252 "The type of keynode(%s) is not INT", keynode->keyname);
1254 return keynode->value.i;
1258 vconf_keynode_get_dbl (keynode_t * keynode)
1260 retvm_if (keynode == NULL, -1.0, "Invalid argument: keynode is NULL");
1261 retvm_if (keynode->type != type_double, -1.0,
1262 "The type of keynode(%s) is not DBL", keynode->keyname);
1264 return keynode->value.d;
1268 vconf_keynode_get_bool (keynode_t * keynode)
1270 retvm_if (keynode == NULL,
1271 VCONF_ERROR, "Invalid argument: keynode is NULL");
1272 retvm_if (keynode->type != type_bool, VCONF_ERROR,
1273 "The type of keynode(%s) is not BOOL", keynode->keyname);
1275 return !!(keynode->value.b);
1279 vconf_keynode_get_str (keynode_t * keynode)
1281 retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL");
1282 retvm_if (keynode->type != type_string, NULL,
1283 "The type of keynode(%s) is not STR", keynode->keyname);
1285 return keynode->value.s;
1289 vconf_set_default_group (const char *groupname)
1293 copy = _dup_groupname_ (groupname);
1296 free (default_group);
1297 default_group = copy;
1302 vconf_keylist_new ()
1305 if (_ensure_default_group_ () != VCONF_OK)
1307 result = calloc (1, sizeof (keylist_t));
1309 internal_list_count += (result != NULL);
1315 vconf_keylist_free (keylist_t * keylist)
1317 keynode_t *keynode, *temp;
1319 retvm_if (keylist == NULL,
1320 VCONF_ERROR, "Invalid argument: keylist is NULL");
1322 keynode = keylist->head;
1326 temp = keynode->next;
1327 _keynode_free_ (keynode);
1332 internal_list_count -= (internal_list_count > 0);
1334 _check_close_buxton_ ();
1339 vconf_keylist_rewind (keylist_t * keylist)
1341 retvm_if (keylist == NULL,
1342 VCONF_ERROR, "Invalid argument: keylist is NULL");
1344 keylist->cursor = NULL;
1350 vconf_keylist_nextnode (keylist_t * keylist)
1354 retvm_if (keylist == NULL, NULL, "Invalid argument: keylist is NULL");
1356 result = keylist->cursor;
1357 result = result == NULL ? keylist->head : result->next;
1358 keylist->cursor = result;
1364 vconf_keylist_lookup (keylist_t * keylist,
1365 const char *keyname, keynode_t ** return_node)
1369 retvm_if (keylist == NULL,
1370 VCONF_ERROR, "Invalid argument: keylist is NULL");
1371 retvm_if (keyname == NULL,
1372 VCONF_ERROR, "Invalid argument: keyname is NULL");
1373 retvm_if (return_node == NULL,
1374 VCONF_ERROR, "Invalid argument: return_node is NULL");
1376 keynode = _keylist_lookup_ (keylist, keyname, NULL);
1377 if (NULL == keynode)
1381 *return_node = keynode;
1382 return keynode->type;
1386 _cb_sort_keynodes (const void *a, const void *b)
1388 register const keynode_t *kna = *(const keynode_t **) a;
1389 register const keynode_t *knb = *(const keynode_t **) b;
1390 return strcmp (kna->keyname, knb->keyname);
1394 vconf_keylist_sort (keylist_t * keylist)
1397 keynode_t **nodes, *keynode;
1399 retvm_if (keylist == NULL,
1400 VCONF_ERROR, "Invalid argument: keylist is NULL");
1402 if (keylist->num <= 1)
1405 nodes = malloc (keylist->num * sizeof *nodes);
1406 retvm_if (nodes == NULL, VCONF_ERROR, "can't allocate memory for sorting");
1409 keynode = keylist->head;
1410 while (keynode != NULL)
1412 assert (index < keylist->num);
1413 nodes[index++] = keynode;
1414 keynode = keynode->next;
1416 assert (index == keylist->num);
1418 qsort (nodes, index, sizeof *nodes, _cb_sort_keynodes);
1422 nodes[--index]->next = keynode;
1423 keynode = nodes[index];
1425 keylist->head = keynode;
1431 vconf_keylist_add_int (keylist_t * keylist, const char *keyname,
1436 retvm_if (keylist == NULL,
1437 VCONF_ERROR, "Invalid argument: keylist is NULL");
1438 retvm_if (keyname == NULL,
1439 VCONF_ERROR, "Invalid argument: keyname is NULL");
1441 keynode = _keylist_getadd_ (keylist, keyname, type_int);
1442 if (keynode == NULL)
1445 keynode->value.i = value;
1446 return keylist->num;
1450 vconf_keylist_add_bool (keylist_t * keylist, const char *keyname,
1455 retvm_if (keylist == NULL,
1456 VCONF_ERROR, "Invalid argument: keylist is NULL");
1457 retvm_if (keyname == NULL,
1458 VCONF_ERROR, "Invalid argument: keyname is NULL");
1460 keynode = _keylist_getadd_ (keylist, keyname, type_bool);
1461 if (keynode == NULL)
1464 keynode->value.b = !!value;
1465 return keylist->num;
1469 vconf_keylist_add_dbl (keylist_t * keylist,
1470 const char *keyname, const double value)
1474 retvm_if (keylist == NULL, VCONF_ERROR,
1475 "Invalid argument: keylist is NULL");
1476 retvm_if (keyname == NULL, VCONF_ERROR,
1477 "Invalid argument: keyname is NULL");
1479 keynode = _keylist_getadd_ (keylist, keyname, type_double);
1480 if (keynode == NULL)
1483 keynode->value.d = value;
1484 return keylist->num;
1488 vconf_keylist_add_str (keylist_t * keylist,
1489 const char *keyname, const char *value)
1494 retvm_if (keylist == NULL, VCONF_ERROR,
1495 "Invalid argument: keylist is NULL");
1496 retvm_if (keyname == NULL, VCONF_ERROR,
1497 "Invalid argument: keyname is NULL");
1499 copy = strdup (value == NULL ? "" : value);
1500 retvm_if (copy == NULL, VCONF_ERROR, "Allocation of memory failed");
1502 keynode = _keylist_getadd_ (keylist, keyname, type_string);
1503 if (keynode == NULL)
1509 free (keynode->value.s);
1510 keynode->value.s = copy;
1511 return keylist->num;
1515 vconf_keylist_add_null (keylist_t * keylist, const char *keyname)
1519 retvm_if (keylist == NULL, VCONF_ERROR,
1520 "Invalid argument: keylist is NULL");
1521 retvm_if (keyname == NULL, VCONF_ERROR,
1522 "Invalid argument: keyname is NULL");
1524 keynode = _keylist_getadd_ (keylist, keyname, type_unset);
1525 if (keynode == NULL)
1528 return keylist->num;
1532 vconf_keylist_del (keylist_t * keylist, const char *keyname)
1534 keynode_t *keynode, **previous = NULL;
1536 retvm_if (keylist == NULL, VCONF_ERROR,
1537 "Invalid argument: keylist is NULL");
1538 retvm_if (keyname == NULL, VCONF_ERROR,
1539 "Invalid argument: keyname is NULL");
1541 keynode = _keylist_lookup_ (keylist, keyname, &previous);
1542 if (keynode == NULL)
1545 *previous = keynode->next;
1547 _keynode_free_ (keynode);
1553 vconf_set (keylist_t * keylist)
1555 retvm_if (keylist == NULL, VCONF_ERROR,
1556 "Invalid argument: keylist is NULL");
1558 return _apply_buxton_on_list_ (keylist, _async_set_or_unset_, NULL);
1562 vconf_set_labels (keylist_t * keylist, const char *label)
1564 retvm_if (keylist == NULL, VCONF_ERROR,
1565 "Invalid argument: keylist is NULL");
1567 retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL");
1569 return _apply_buxton_on_list_ (keylist, _async_set_label_, label);
1573 vconf_sync_key (const char *keyname)
1576 * does nothing succefully
1582 vconf_refresh (keylist_t * keylist)
1584 retvm_if (keylist == NULL, VCONF_ERROR,
1585 "Invalid argument: keylist is NULL");
1587 return _apply_buxton_on_list_ (keylist, _async_refresh_, NULL);
1591 vconf_scan (keylist_t * keylist, const char *dirpath, get_option_t option)
1594 struct layer_key laykey;
1595 struct scanning_data data;
1598 retvm_if (keylist == NULL, VCONF_ERROR,
1599 "Invalid argument: keylist is null");
1600 retvm_if (keylist->num != 0, VCONF_ERROR,
1601 "Invalid argument: keylist not empty");
1602 retvm_if (dirpath == NULL, VCONF_ERROR,
1603 "Invalid argument: dirpath is null");
1604 retvm_if (_check_keyname_ (dirpath) == 0, VCONF_ERROR,
1605 "Invalid argument: dirpath is not valid");
1607 status = _open_buxton_ ();
1610 ERR ("Can't connect to buxton");
1614 data.keylist = keylist;
1619 data.want_directories = 0;
1621 data.is_recursive = 0;
1624 data.want_directories = 1;
1626 data.is_recursive = 0;
1629 data.want_directories = 1;
1631 data.is_recursive = 0;
1633 case VCONF_GET_KEY_REC:
1634 data.want_directories = 0;
1636 data.is_recursive = 1;
1638 case VCONF_GET_ALL_REC:
1639 data.want_directories = 1;
1641 data.is_recursive = 1;
1643 case VCONF_GET_DIR_REC:
1644 data.want_directories = 0;
1646 data.is_recursive = 1;
1649 ERR ("Invalid argument: Bad option value");
1653 data.dirlen = strlen (dirpath);
1654 assert (data.dirlen);
1655 if (dirpath[data.dirlen - 1] == '/')
1657 data.directory = dirpath;
1662 status = asprintf (&dircopy, "%s/", dirpath);
1663 retvm_if (status < 0, VCONF_ERROR,
1664 "No more memory for copying dirpath");
1665 data.directory = dircopy;
1669 status = _get_layer_key_ (data.directory, &laykey);
1670 if (status != VCONF_OK)
1675 data.prefix = laykey.prefix;
1682 assert (_buxton_ () != NULL);
1683 status = buxton_list_names (_buxton_ (), laykey.layer, default_group,
1684 laykey.key, (BuxtonCallback) _cb_scan_,
1687 status = _wait_buxton_response_ (&data.pending);
1691 retvm_if (status, VCONF_ERROR, "Error while calling buxton_list_names: %m");
1692 if (data.cb_status != VCONF_OK)
1697 return vconf_refresh (keylist);
1701 vconf_get (keylist_t * keylist, const char *dirpath, get_option_t option)
1703 if (option == VCONF_REFRESH_ONLY
1704 || (option == VCONF_GET_KEY && keylist->num != 0))
1706 return vconf_refresh (keylist);
1710 return vconf_scan (keylist, dirpath, option);
1715 vconf_unset (const char *keyname)
1717 struct singleton single;
1720 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1722 status = _keylist_init_singleton_ (&single, keyname, type_delete);
1723 if (status == VCONF_OK)
1725 status = vconf_set (&single.list);
1732 vconf_exists (const char *keyname)
1734 struct singleton single;
1737 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1739 status = _keylist_init_singleton_ (&single, keyname, type_unset);
1740 if (status == VCONF_OK)
1742 status = vconf_refresh (&single.list);
1743 if (status == VCONF_OK && single.node.type == type_string)
1744 free (single.node.value.s);
1751 vconf_unset_recursive (const char *in_dir)
1753 struct _keylist_t *keylist;
1754 struct _keynode_t *keynode;
1757 retvm_if (in_dir == NULL, VCONF_ERROR, "Invalid argument: dir is null");
1759 keylist = vconf_keylist_new ();
1760 if (keylist == NULL)
1763 status = vconf_scan (keylist, in_dir, VCONF_GET_KEY_REC);
1764 if (status == VCONF_OK)
1766 for (keynode = keylist->head; keynode; keynode = keynode->next)
1767 keynode->type = type_delete;
1768 status = vconf_set (keylist);
1770 vconf_keylist_free (keylist);
1775 vconf_notify_key_changed (const char *keyname, vconf_callback_fn cb,
1779 struct notify *notif;
1780 keynode_t *keynode, *aknode;
1783 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null");
1784 retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
1785 status = _open_buxton_ ();
1786 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1787 status = vconf_exists (keyname);
1788 retvm_if (status != VCONF_OK, VCONF_ERROR, "key %s doesn't exist", keyname);
1792 * create the notification
1794 notif = malloc (sizeof *notif);
1795 retvm_if (notif == NULL, VCONF_ERROR,
1796 "Allocation of notify structure failed");
1799 * ensure existing list
1802 if (notify_keylist == NULL)
1804 notify_keylist = vconf_keylist_new ();
1805 if (notify_keylist == NULL)
1814 * search keynode of keyname
1816 keynode = _keylist_lookup_ (notify_keylist, keyname, NULL);
1817 if (keynode == NULL)
1820 * not found, create it with type unset
1822 keynode = _keylist_add_ (notify_keylist, keyname, type_unset);
1823 if (keynode == NULL)
1832 * init the notification
1834 notif->callback = cb;
1835 notif->userdata = user_data;
1836 notif->keynode = keynode;
1837 notif->next = notify_entries;
1838 notify_entries = notif;
1842 * record the notification
1844 status = _notify_reg_unreg_ (notif, true);
1845 if (status != VCONF_OK)
1847 vconf_ignore_key_changed (keyname, cb);
1851 #if !defined(NO_GLIB)
1852 return _glib_start_watch_ ();
1859 vconf_ignore_key_changed (const char *keyname, vconf_callback_fn cb)
1861 struct notify *entry, **prevent, *delent, **prevdelent;
1862 keynode_t *keynode, **prevnod;
1866 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null");
1867 retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
1868 status = _open_buxton_ ();
1869 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1872 status = VCONF_ERROR;
1876 if (notify_keylist != NULL)
1878 keynode = _keylist_lookup_ (notify_keylist, keyname, &prevnod);
1879 if (keynode != NULL)
1881 prevdelent = &delent;
1882 prevent = ¬ify_entries;
1883 entry = notify_entries;
1884 while (entry != NULL)
1886 if (entry->keynode == keynode)
1888 if (entry->callback == cb)
1890 *prevdelent = entry;
1891 prevdelent = &entry->next;
1892 entry = entry->next;
1898 prevent = &entry->next;
1899 entry = entry->next;
1904 *prevnod = keynode->next;
1905 #if !defined(NO_GLIB)
1906 if (notify_entries == NULL)
1907 _glib_stop_watch_ ();
1912 while (delent != NULL)
1915 delent = entry->next;
1916 _notify_reg_unreg_ (entry, false);
1920 _keynode_free_ (keynode);
1926 ERR ("Not found: can't remove notification for key(%s)", keyname);
1932 vconf_set_int (const char *keyname, const int intval)
1934 struct singleton single;
1937 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1939 status = _keylist_init_singleton_ (&single, keyname, type_int);
1940 if (status == VCONF_OK)
1942 single.node.value.i = intval;
1943 status = vconf_set (&single.list);
1949 vconf_set_bool (const char *keyname, const int boolval)
1951 struct singleton single;
1954 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1956 status = _keylist_init_singleton_ (&single, keyname, type_bool);
1957 if (status == VCONF_OK)
1959 single.node.value.b = (bool) boolval;
1960 status = vconf_set (&single.list);
1966 vconf_set_dbl (const char *keyname, const double dblval)
1968 struct singleton single;
1971 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1973 status = _keylist_init_singleton_ (&single, keyname, type_double);
1974 if (status == VCONF_OK)
1976 single.node.value.d = dblval;
1977 status = vconf_set (&single.list);
1983 vconf_set_str (const char *keyname, const char *strval)
1985 struct singleton single;
1988 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1990 status = _keylist_init_singleton_ (&single, keyname, type_string);
1991 if (status == VCONF_OK)
1993 single.node.value.s = (char *) strval;
1994 status = vconf_set (&single.list);
2000 vconf_get_int (const char *keyname, int *intval)
2002 struct singleton single;
2005 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2007 status = _keylist_init_singleton_ (&single, keyname, type_int);
2008 if (status == VCONF_OK)
2010 status = vconf_refresh (&single.list);
2011 if (status == VCONF_OK)
2012 *intval = single.node.value.i;
2018 vconf_set_label (const char *keyname, const char *label)
2020 struct singleton single;
2023 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2025 retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL");
2027 status = _keylist_init_singleton_ (&single, keyname, type_unset);
2028 if (status == VCONF_OK)
2030 status = vconf_set_labels (&single.list, label);
2036 vconf_get_bool (const char *keyname, int *boolval)
2038 struct singleton single;
2041 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2043 status = _keylist_init_singleton_ (&single, keyname, type_bool);
2044 if (status == VCONF_OK)
2046 status = vconf_refresh (&single.list);
2047 if (status == VCONF_OK)
2048 *boolval = (int) single.node.value.b;
2054 vconf_get_dbl (const char *keyname, double *dblval)
2056 struct singleton single;
2059 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2061 status = _keylist_init_singleton_ (&single, keyname, type_double);
2062 if (status == VCONF_OK)
2064 status = vconf_refresh (&single.list);
2065 if (status == VCONF_OK)
2066 *dblval = single.node.value.d;
2072 vconf_get_str (const char *keyname)
2074 struct singleton single;
2077 retvm_if (keyname == NULL, NULL, "Invalid argument: key is NULL");
2079 status = _keylist_init_singleton_ (&single, keyname, type_string);
2080 if (status != VCONF_OK)
2083 single.node.value.s = NULL;
2084 status = vconf_refresh (&single.list);
2085 if (status != VCONF_OK)
2088 return single.node.value.s;
2092 vconf_get_ext_errno (void)
2094 INFO("vconf errno: %d", g_vconf_errno);
2095 return g_vconf_errno;