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"
61 #define VCONF_ERROR -1
63 /*================= SECTION definition of types =============*/
66 * internal types for keys
70 type_unset, /* type unset or unknown */
71 type_directory, /* a directory, not a real key */
72 type_delete, /* key to be deleted */
73 type_string, /* key of type string */
74 type_int, /* key of type integer */
75 type_double, /* key of type double */
76 type_bool /* key of type boolean */
80 * union for storing values
84 int i; /* storage of integers */
85 int b; /* storage of booleans */
86 double d; /* storage of doubles */
87 char *s; /* storage of strings */
95 enum keytype type; /* type of the key */
96 union keyvalue value; /* value of the key */
97 keynode_t *next; /* linking to the next key */
98 keylist_t *list; /* the containing list */
99 const char *keyname; /* name of the key */
103 * structure for list of keys
107 int num; /* count of keys in the list */
108 keynode_t *head; /* first key of the list */
109 keynode_t *cursor; /* iterator on keys for clients */
110 int cb_active; /* callback global activity */
111 int cb_status; /* callback global status */
112 unsigned cb_sent; /* callback global count of sent queries */
113 unsigned cb_received; /* callback global count of
114 * received responses */
118 * data for the callback of scanning
122 int pending; /* is the scan pending? */
123 int cb_status; /* status of the call back */
124 int want_directories; /* is scanning directories? */
125 int want_keys; /* is scanning keys? */
126 int is_recursive; /* is scanning recursively? */
127 size_t dirlen; /* length of the directory */
128 keylist_t *keylist; /* keylist to fill */
129 const char *prefix; /* prefix to add in front of names */
130 const char *directory; /* scanned directory */
134 * data when translating vconf names to buxton names. ** the rule is that
139 const char *layer; /* identified layer-name */
140 const char *prefix; /* vconf prefix of the name (without
142 const char *key; /* buxton key-name (without leading /) */
146 * singleton data for facilities
150 keylist_t list; /* the list */
151 keynode_t node; /* its single node */
155 * structure for notifications
159 int status; /* callback status */
160 vconf_callback_fn callback; /* the user callback */
161 void *userdata; /* the user data */
162 keynode_t *keynode; /* the recorded key node */
163 struct notify *next; /* tink to the next notification */
166 /*================= SECTION local variables =============*/
169 * maximum length of key-names
171 static size_t keyname_maximum_length = 2030;
174 * maximum length of group-names
176 static size_t keygroup_maximum_length = 1010;
179 * association from prefixes to layers
181 static const char *assoc_prefix_layer[][2] = {
185 {"memory_init", "base"},
191 * default timeout in scanning responses
193 static int default_timeout = 5000; /* in milliseconds */
196 * instance of the buxton client
198 static BuxtonClient the_buxton_client = 0;
201 * the file handle number for polling buxton events
203 static int the_buxton_client_fd = 0;
206 * flag indacating if the buxton client is set or not
208 static char the_buxton_client_is_set = 0;
211 * the group to use if default group is unset
213 static const char initial_default_group[] = "vconf";
216 * the default group to use
218 static char *default_group = NULL;
223 static keylist_t *notify_keylist = NULL;
228 static struct notify *notify_entries = NULL;
233 static int internal_list_count = 0;
235 #if !defined(NO_GLIB)
237 * link to the glib main loop
239 static GSource *glib_source = NULL;
242 #if !defined(NO_MULTITHREADING)
244 * multithreaded protection
245 * CAUTION: always use the given order!
247 static pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER;
248 static pthread_mutex_t mutex_counter = PTHREAD_MUTEX_INITIALIZER;
249 static pthread_mutex_t mutex_buxton = PTHREAD_MUTEX_INITIALIZER;
250 static pthread_mutex_t mutex_group = PTHREAD_MUTEX_INITIALIZER;
251 #define LOCK(x) pthread_mutex_lock(&mutex_##x)
252 #define UNLOCK(x) pthread_mutex_unlock(&mutex_##x)
258 /*================= SECTION utils =============*/
261 * duplication of a string with validation of the length
264 _dup_ (const char *source, size_t maxlen, const char *tag)
269 assert (source != NULL);
270 length = strlen (source);
271 if (length >= maxlen)
273 ERR ("Invalid argument: %s is too long", tag);
276 result = malloc (++length);
279 ERR ("Can't allocate memory for %s", tag);
282 memcpy (result, source, length);
286 /*================= SECTION groupname utils =============*/
289 _dup_groupname_ (const char *groupname)
291 return _dup_ (groupname, keygroup_maximum_length, "group-name");
295 _ensure_default_group_ ()
297 int result = VCONF_OK;
300 if (default_group == NULL)
302 default_group = _dup_groupname_ (initial_default_group);
303 if (default_group == NULL)
304 result = VCONF_ERROR;
311 /*================= SECTION key utils =============*/
314 _keynode_free_ (keynode_t * keynode)
316 assert (keynode != NULL);
317 if (keynode->type == type_string)
318 free (keynode->value.s);
323 _check_keyname_ (const char *keyname)
327 assert (keyname != NULL);
334 for (result = 0; keyname[result]; result++)
336 if (keyname[result] == '/' && keyname[result + 1] == '/')
345 /*================= SECTION list utils =============*/
348 * search in 'keylist' an entry of 'keyname' and return it if found or
349 * NULL if not found. 'previous' if not NULL and if the entry is found
350 * will recieve the address of the pointer referencing the returned node.
352 static inline keynode_t *
353 _keylist_lookup_ (keylist_t * keylist,
354 const char *keyname, keynode_t *** previous)
356 keynode_t *node, **prev;
357 size_t length = 1 + strlen (keyname);
359 prev = &keylist->head;
360 node = keylist->head;
363 assert (node->keyname != NULL);
364 if (!memcmp (keyname, node->keyname, length))
377 static inline keynode_t *
378 _keylist_add_ (keylist_t * keylist, const char *keyname, enum keytype type)
385 * not found, create it
387 length = _check_keyname_ (keyname);
388 retvm_if (!length, NULL, "invalid keyname");
389 retvm_if (length > keyname_maximum_length, NULL, "keyname too long");
390 result = malloc (1 + length + sizeof *result);
391 retvm_if (result == NULL, NULL, "allocation of keynode failed");
393 result->value.s = NULL;
395 result->list = keylist;
396 name = (char *) (result + 1);
397 result->keyname = name;
398 memcpy (name, keyname, length + 1);
400 result->next = keylist->head;
401 keylist->head = result;
407 static inline keynode_t *
408 _keylist_getadd_ (keylist_t * keylist, const char *keyname, enum keytype type)
413 * search keynode of keyname
415 result = _keylist_lookup_ (keylist, keyname, NULL);
419 * not found, create it
421 result = _keylist_add_ (keylist, keyname, type);
423 else if (result->type != type)
425 if (result->type == type_string)
426 free (result->value.s);
428 result->value.s = NULL;
434 _keylist_init_singleton_ (struct singleton *singleton, const char *keyname,
439 if (!_check_keyname_ (keyname))
441 ERR ("Invalid key name(%s)", keyname);
444 status = _ensure_default_group_ ();
445 if (status != VCONF_OK)
448 memset (singleton, 0, sizeof *singleton);
449 singleton->list.num = 1;
450 singleton->list.head = &singleton->node;
451 singleton->node.keyname = keyname;
452 singleton->node.type = type;
453 singleton->node.list = &singleton->list;
459 /*================= SECTION buxton =============*/
462 _check_close_buxton_ ()
468 if (internal_list_count == 0 && notify_entries == NULL)
469 if (internal_list_count == 0 && notify_entries == NULL)
472 bc = the_buxton_client;
473 the_buxton_client_is_set = 0;
474 the_buxton_client = NULL;
475 the_buxton_client_fd = -1;
485 _try_to_open_buxton_ ()
487 the_buxton_client_fd = buxton_open (&the_buxton_client);
488 if (the_buxton_client_fd < 0)
490 ERR ("can't connect to buxton server: %m");
492 the_buxton_client = NULL;
500 if (!the_buxton_client_is_set)
503 * first time, try to connect to buxton
505 the_buxton_client_is_set = 1;
506 _try_to_open_buxton_ ();
509 return the_buxton_client != NULL;
513 static inline BuxtonClient
516 BuxtonClient result = the_buxton_client;
517 assert (result != NULL);
522 _handle_buxton_response_ (int lock)
528 result = buxton_client_handle_response (_buxton_ ());
530 ERR ("Error in buxton_client_handle_response: %m");
532 ERR ("Connection closed");
541 _dispatch_buxton_ (int writing, int lock)
546 assert (_buxton_ () != NULL);
548 pfd.fd = the_buxton_client_fd;
549 pfd.events = writing ? POLLIN | POLLOUT : POLLIN;
553 status = poll (&pfd, 1, default_timeout);
561 else if (status == 1)
563 if (pfd.revents & POLLIN)
565 status = _handle_buxton_response_ (lock);
575 if (pfd.revents & POLLOUT)
588 _wait_buxton_response_ (int *pending)
594 result = _dispatch_buxton_ (0, 1);
596 while (result == VCONF_OK && *pending);
601 _get_layer_key_ (const char *keyname, struct layer_key *laykey)
610 prefix = assoc_prefix_layer[i][0];
611 while (prefix != NULL)
613 for (j = 0; prefix[j] && prefix[j] == keyname[j]; j++);
614 if (!prefix[j] && (!keyname[j] || keyname[j] == '/'))
616 laykey->prefix = prefix;
617 laykey->layer = assoc_prefix_layer[i][1];
618 #if defined(REMOVE_PREFIXES)
619 laykey->key = keyname + j + (keyname[j] == '/');
621 laykey->key = keyname;
626 prefix = assoc_prefix_layer[i][0];
628 ERR ("Invalid argument: wrong prefix of key(%s)", keyname);
632 static inline BuxtonKey
633 _get_buxton_key_ (keynode_t * node)
636 struct layer_key laykey;
641 if (_get_layer_key_ (node->keyname, &laykey) != VCONF_OK)
652 type = BUXTON_TYPE_STRING;
655 type = BUXTON_TYPE_INT32;
658 type = BUXTON_TYPE_DOUBLE;
661 type = BUXTON_TYPE_BOOLEAN;
664 type = BUXTON_TYPE_UNSET;
667 return buxton_key_create (default_group, laykey.key, laykey.layer, type);
670 /*================= SECTION set/unset/refresh =============*/
673 _cb_inc_received_ (BuxtonResponse resp, keynode_t * keynode)
677 assert (keynode != NULL);
678 assert (keynode->list != NULL);
680 list = keynode->list;
682 if (buxton_response_status (resp) != 0)
684 ERR ("Buxton returned error %d for key %s",
685 buxton_response_status (resp), keynode->keyname);
686 list->cb_status = VCONF_ERROR;
691 _set_response_to_keynode_ (BuxtonResponse resp, keynode_t * keynode,
695 BuxtonDataType buxtyp;
698 assert (keynode != NULL);
699 assert (buxton_response_status (resp) == 0);
701 buxtyp = buxton_response_value_type (resp);
704 case BUXTON_TYPE_STRING:
707 case BUXTON_TYPE_INT32:
710 case BUXTON_TYPE_DOUBLE:
713 case BUXTON_TYPE_BOOLEAN:
720 if (force && type != keynode->type && keynode->type != type_unset)
723 buxval = buxton_response_value (resp);
727 if (keynode->type == type_string)
728 free (keynode->value.s);
730 keynode->type = type;
734 keynode->value.s = buxval;
737 keynode->value.i = (int) *(int32_t *) buxval;
740 keynode->value.d = *(double *) buxval;
743 keynode->value.b = *(bool *) buxval;
754 _cb_refresh_ (BuxtonResponse resp, keynode_t * keynode)
758 assert (keynode != NULL);
759 assert (keynode->list != NULL);
760 assert (buxton_response_type (resp) == BUXTON_CONTROL_GET);
762 list = keynode->list;
764 if (buxton_response_status (resp) != 0)
766 ERR ("Error %d while getting buxton key %s",
767 buxton_response_status (resp), keynode->keyname);
768 list->cb_status = VCONF_ERROR;
770 else if (_set_response_to_keynode_ (resp, keynode, 0) != VCONF_OK)
772 list->cb_status = VCONF_ERROR;
777 _cb_scan_ (BuxtonResponse resp, struct scanning_data *data)
791 * check the response status
793 if (buxton_response_status (resp) != 0)
795 ERR ("Error while getting list of names from buxton");
796 data->cb_status = VCONF_ERROR;
801 * iterate on the list of names
803 assert (data->directory[data->dirlen - 1] == '/');
804 keylist = data->keylist;
805 count = buxton_response_list_names_count (resp);
807 while (index < count)
812 buxname = buxton_response_list_names_item (resp, index++);
815 ERR ("Unexpected NULL name returned by buxton");
816 data->cb_status = VCONF_ERROR;
823 #if defined(REMOVE_PREFIXES)
824 length = asprintf (&name, "%s/%s", data->prefix, buxname);
826 length = asprintf (&name, "%s", buxname);
831 ERR ("Memory allocation error");
832 data->cb_status = VCONF_ERROR;
835 assert (_check_keyname_ (name));
836 assert (!memcmp (data->directory, name, data->dirlen));
839 * add key if requested
841 term = strchr (name + data->dirlen, '/');
842 if (data->want_keys && (data->is_recursive || term == NULL))
844 keynode = _keylist_getadd_ (keylist, name, type_unset);
848 data->cb_status = VCONF_ERROR;
854 * add directories if requested
856 if (data->want_directories)
861 keynode = _keylist_getadd_ (keylist, name, type_directory);
865 data->cb_status = VCONF_ERROR;
868 if (!data->is_recursive)
873 term = strchr (term + 1, '/');
879 data->cb_status = VCONF_OK;
884 _async_set_ (keynode_t * keynode)
890 assert (keynode != NULL);
892 switch (keynode->type)
895 data = keynode->value.s;
900 data = &keynode->value;
906 key = _get_buxton_key_ (keynode);
912 status = buxton_set_value (_buxton_ (), key,
914 (BuxtonCallback) _cb_inc_received_, keynode,
916 buxton_key_free (key);
923 ERR ("Error while calling buxton_set_value: %m");
928 _async_unset_ (keynode_t * keynode)
933 assert (keynode != NULL);
935 if (keynode->type != type_delete)
940 key = _get_buxton_key_ (keynode);
946 status = buxton_unset_value (_buxton_ (), key,
947 (BuxtonCallback) _cb_inc_received_,
949 buxton_key_free (key);
956 ERR ("Error while calling buxton_unset_value: %m");
961 _async_set_or_unset_ (keynode_t * keynode, const char *unused)
963 assert (keynode != NULL);
965 switch (keynode->type)
971 return _async_unset_ (keynode);
973 return _async_set_ (keynode);
978 _async_refresh_ (keynode_t * keynode, const char *unused)
983 assert (keynode != NULL);
985 switch (keynode->type)
997 key = _get_buxton_key_ (keynode);
1003 status = buxton_get_value (_buxton_ (), key,
1004 (BuxtonCallback) _cb_refresh_, keynode, false);
1005 buxton_key_free (key);
1012 ERR ("Error while calling buxton_get_value: %m");
1017 _async_set_label_ (keynode_t * keynode, const char *label)
1022 assert (keynode != NULL);
1024 key = _get_buxton_key_ (keynode);
1030 status = buxton_set_label (_buxton_ (), key, label,
1031 (BuxtonCallback) _cb_inc_received_,
1033 buxton_key_free (key);
1040 ERR ("Error while calling buxton_set_label: %m");
1046 _apply_buxton_on_list_ (keylist_t * keylist,
1047 int (*async) (keynode_t *, const char *),
1054 assert (keylist != NULL);
1056 status = _open_buxton_ ();
1057 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1058 assert (_buxton_ () != NULL);
1060 retvm_if (keylist->cb_active != 0, VCONF_ERROR,
1061 "Already active in vconf-buxton");
1065 keylist->cb_active = 1;
1066 keylist->cb_status = VCONF_OK;
1067 keylist->cb_sent = 0;
1068 keylist->cb_received = 0;
1070 keynode = keylist->head;
1071 status = _dispatch_buxton_ (1, 0);
1072 while (keynode != NULL && status == VCONF_OK)
1074 sent = async (keynode, data);
1075 keynode = keynode->next;
1078 status = VCONF_ERROR;
1082 keylist->cb_sent += sent;
1083 status = _dispatch_buxton_ (1, 0);
1090 while (status == VCONF_OK && keylist->cb_sent != keylist->cb_received)
1092 status = _dispatch_buxton_ (0, 0);
1095 if (status == VCONF_OK && keylist->cb_status != VCONF_OK)
1096 status = keylist->cb_status;
1097 keylist->cb_active = 0;
1101 _check_close_buxton_ ();
1106 /*================= SECTION notification =============*/
1109 _cb_notify_ (BuxtonResponse resp, struct notify *notif)
1111 switch (buxton_response_type (resp))
1113 case BUXTON_CONTROL_NOTIFY:
1114 case BUXTON_CONTROL_UNNOTIFY:
1116 buxton_response_status (resp) == 0 ? VCONF_OK : VCONF_ERROR;
1118 case BUXTON_CONTROL_CHANGED:
1119 if (_set_response_to_keynode_ (resp, notif->keynode, 1) == VCONF_OK)
1122 notif->callback (notif->keynode, notif->userdata);
1132 _notify_reg_unreg_ (struct notify *notif, bool reg)
1137 status = _open_buxton_ ();
1138 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1141 key = _get_buxton_key_ (notif->keynode);
1142 retvm_if (key == NULL, VCONF_ERROR, "Can't create buxton key");
1143 notif->status = VCONF_OK; /* on success calback isn't called! */
1145 (reg ? buxton_register_notification :
1146 buxton_unregister_notification) (_buxton_ (), key,
1147 (BuxtonCallback) _cb_notify_,
1149 buxton_key_free (key);
1151 return status == 0 && notif->status == VCONF_OK ? VCONF_OK : VCONF_ERROR;
1154 #if !defined(NO_GLIB)
1155 /*================= SECTION glib =============*/
1158 _cb_glib_ (GIOChannel * src, GIOCondition cond, gpointer data)
1162 status = _handle_buxton_response_ (1);
1165 return G_SOURCE_REMOVE;
1167 return G_SOURCE_CONTINUE;
1171 _glib_start_watch_ ()
1175 if (glib_source != NULL)
1178 gio = g_io_channel_unix_new (the_buxton_client_fd);
1179 retvm_if (gio == NULL, VCONF_ERROR, "Error: create a new GIOChannel");
1181 g_io_channel_set_flags (gio, G_IO_FLAG_NONBLOCK, NULL);
1183 glib_source = g_io_create_watch (gio, G_IO_IN);
1184 if (glib_source == NULL)
1186 ERR ("Error: create a new GSource");
1187 g_io_channel_unref (gio);
1191 g_source_set_callback (glib_source, (GSourceFunc) _cb_glib_, NULL, NULL);
1192 g_source_attach (glib_source, NULL);
1193 g_io_channel_unref (gio);
1194 g_source_unref (glib_source);
1200 _glib_stop_watch_ ()
1202 if (glib_source != NULL)
1204 g_source_destroy (glib_source);
1210 /*================= SECTION VCONF API =============*/
1213 vconf_keynode_get_name (keynode_t * keynode)
1215 retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL");
1216 retvm_if (keynode->keyname == NULL, NULL, "The name of keynode is NULL");
1218 return keynode->keyname;
1222 vconf_keynode_get_type (keynode_t * keynode)
1224 retvm_if (keynode == NULL,
1225 VCONF_ERROR, "Invalid argument: keynode is NULL");
1227 switch (keynode->type)
1229 case type_directory:
1230 return VCONF_TYPE_DIR;
1232 return VCONF_TYPE_STRING;
1234 return VCONF_TYPE_INT;
1236 return VCONF_TYPE_DOUBLE;
1238 return VCONF_TYPE_BOOL;
1240 return VCONF_TYPE_NONE;
1245 vconf_keynode_get_int (keynode_t * keynode)
1247 retvm_if (keynode == NULL,
1248 VCONF_ERROR, "Invalid argument: keynode is NULL");
1249 retvm_if (keynode->type != type_int, VCONF_ERROR,
1250 "The type of keynode(%s) is not INT", keynode->keyname);
1252 return keynode->value.i;
1256 vconf_keynode_get_dbl (keynode_t * keynode)
1258 retvm_if (keynode == NULL, -1.0, "Invalid argument: keynode is NULL");
1259 retvm_if (keynode->type != type_double, -1.0,
1260 "The type of keynode(%s) is not DBL", keynode->keyname);
1262 return keynode->value.d;
1266 vconf_keynode_get_bool (keynode_t * keynode)
1268 retvm_if (keynode == NULL,
1269 VCONF_ERROR, "Invalid argument: keynode is NULL");
1270 retvm_if (keynode->type != type_bool, VCONF_ERROR,
1271 "The type of keynode(%s) is not BOOL", keynode->keyname);
1273 return !!(keynode->value.b);
1277 vconf_keynode_get_str (keynode_t * keynode)
1279 retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL");
1280 retvm_if (keynode->type != type_string, NULL,
1281 "The type of keynode(%s) is not STR", keynode->keyname);
1283 return keynode->value.s;
1287 vconf_set_default_group (const char *groupname)
1291 copy = _dup_groupname_ (groupname);
1294 free (default_group);
1295 default_group = copy;
1300 vconf_keylist_new ()
1303 if (_ensure_default_group_ () != VCONF_OK)
1305 result = calloc (1, sizeof (keylist_t));
1307 internal_list_count += (result != NULL);
1313 vconf_keylist_free (keylist_t * keylist)
1315 keynode_t *keynode, *temp;
1317 retvm_if (keylist == NULL,
1318 VCONF_ERROR, "Invalid argument: keylist is NULL");
1320 keynode = keylist->head;
1324 temp = keynode->next;
1325 _keynode_free_ (keynode);
1330 internal_list_count -= (internal_list_count > 0);
1332 _check_close_buxton_ ();
1337 vconf_keylist_rewind (keylist_t * keylist)
1339 retvm_if (keylist == NULL,
1340 VCONF_ERROR, "Invalid argument: keylist is NULL");
1342 keylist->cursor = NULL;
1348 vconf_keylist_nextnode (keylist_t * keylist)
1352 retvm_if (keylist == NULL, NULL, "Invalid argument: keylist is NULL");
1354 result = keylist->cursor;
1355 result = result == NULL ? keylist->head : result->next;
1356 keylist->cursor = result;
1362 vconf_keylist_lookup (keylist_t * keylist,
1363 const char *keyname, keynode_t ** return_node)
1367 retvm_if (keylist == NULL,
1368 VCONF_ERROR, "Invalid argument: keylist is NULL");
1369 retvm_if (keyname == NULL,
1370 VCONF_ERROR, "Invalid argument: keyname is NULL");
1371 retvm_if (return_node == NULL,
1372 VCONF_ERROR, "Invalid argument: return_node is NULL");
1374 keynode = _keylist_lookup_ (keylist, keyname, NULL);
1375 if (NULL == keynode)
1379 *return_node = keynode;
1380 return keynode->type;
1384 _cb_sort_keynodes (const void *a, const void *b)
1386 register const keynode_t *kna = *(const keynode_t **) a;
1387 register const keynode_t *knb = *(const keynode_t **) b;
1388 return strcmp (kna->keyname, knb->keyname);
1392 vconf_keylist_sort (keylist_t * keylist)
1395 keynode_t **nodes, *keynode;
1397 retvm_if (keylist == NULL,
1398 VCONF_ERROR, "Invalid argument: keylist is NULL");
1400 if (keylist->num <= 1)
1403 nodes = malloc (keylist->num * sizeof *nodes);
1404 retvm_if (nodes == NULL, VCONF_ERROR, "can't allocate memory for sorting");
1407 keynode = keylist->head;
1408 while (keynode != NULL)
1410 assert (index < keylist->num);
1411 nodes[index++] = keynode;
1412 keynode = keynode->next;
1414 assert (index == keylist->num);
1416 qsort (nodes, index, sizeof *nodes, _cb_sort_keynodes);
1420 nodes[--index]->next = keynode;
1421 keynode = nodes[index];
1423 keylist->head = keynode;
1429 vconf_keylist_add_int (keylist_t * keylist, const char *keyname,
1434 retvm_if (keylist == NULL,
1435 VCONF_ERROR, "Invalid argument: keylist is NULL");
1436 retvm_if (keyname == NULL,
1437 VCONF_ERROR, "Invalid argument: keyname is NULL");
1439 keynode = _keylist_getadd_ (keylist, keyname, type_int);
1440 if (keynode == NULL)
1443 keynode->value.i = value;
1444 return keylist->num;
1448 vconf_keylist_add_bool (keylist_t * keylist, const char *keyname,
1453 retvm_if (keylist == NULL,
1454 VCONF_ERROR, "Invalid argument: keylist is NULL");
1455 retvm_if (keyname == NULL,
1456 VCONF_ERROR, "Invalid argument: keyname is NULL");
1458 keynode = _keylist_getadd_ (keylist, keyname, type_bool);
1459 if (keynode == NULL)
1462 keynode->value.b = !!value;
1463 return keylist->num;
1467 vconf_keylist_add_dbl (keylist_t * keylist,
1468 const char *keyname, const double value)
1472 retvm_if (keylist == NULL, VCONF_ERROR,
1473 "Invalid argument: keylist is NULL");
1474 retvm_if (keyname == NULL, VCONF_ERROR,
1475 "Invalid argument: keyname is NULL");
1477 keynode = _keylist_getadd_ (keylist, keyname, type_double);
1478 if (keynode == NULL)
1481 keynode->value.d = value;
1482 return keylist->num;
1486 vconf_keylist_add_str (keylist_t * keylist,
1487 const char *keyname, const char *value)
1492 retvm_if (keylist == NULL, VCONF_ERROR,
1493 "Invalid argument: keylist is NULL");
1494 retvm_if (keyname == NULL, VCONF_ERROR,
1495 "Invalid argument: keyname is NULL");
1497 copy = strdup (value == NULL ? "" : value);
1498 retvm_if (copy == NULL, VCONF_ERROR, "Allocation of memory failed");
1500 keynode = _keylist_getadd_ (keylist, keyname, type_string);
1501 if (keynode == NULL)
1507 free (keynode->value.s);
1508 keynode->value.s = copy;
1509 return keylist->num;
1513 vconf_keylist_add_null (keylist_t * keylist, const char *keyname)
1517 retvm_if (keylist == NULL, VCONF_ERROR,
1518 "Invalid argument: keylist is NULL");
1519 retvm_if (keyname == NULL, VCONF_ERROR,
1520 "Invalid argument: keyname is NULL");
1522 keynode = _keylist_getadd_ (keylist, keyname, type_unset);
1523 if (keynode == NULL)
1526 return keylist->num;
1530 vconf_keylist_del (keylist_t * keylist, const char *keyname)
1532 keynode_t *keynode, **previous = NULL;
1534 retvm_if (keylist == NULL, VCONF_ERROR,
1535 "Invalid argument: keylist is NULL");
1536 retvm_if (keyname == NULL, VCONF_ERROR,
1537 "Invalid argument: keyname is NULL");
1539 keynode = _keylist_lookup_ (keylist, keyname, &previous);
1540 if (keynode == NULL)
1543 *previous = keynode->next;
1545 _keynode_free_ (keynode);
1551 vconf_set (keylist_t * keylist)
1553 retvm_if (keylist == NULL, VCONF_ERROR,
1554 "Invalid argument: keylist is NULL");
1556 return _apply_buxton_on_list_ (keylist, _async_set_or_unset_, NULL);
1560 vconf_set_labels (keylist_t * keylist, const char *label)
1562 retvm_if (keylist == NULL, VCONF_ERROR,
1563 "Invalid argument: keylist is NULL");
1565 retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL");
1567 return _apply_buxton_on_list_ (keylist, _async_set_label_, label);
1571 vconf_sync_key (const char *keyname)
1574 * does nothing succefully
1580 vconf_refresh (keylist_t * keylist)
1582 retvm_if (keylist == NULL, VCONF_ERROR,
1583 "Invalid argument: keylist is NULL");
1585 return _apply_buxton_on_list_ (keylist, _async_refresh_, NULL);
1589 vconf_scan (keylist_t * keylist, const char *dirpath, get_option_t option)
1592 struct layer_key laykey;
1593 struct scanning_data data;
1596 retvm_if (keylist == NULL, VCONF_ERROR,
1597 "Invalid argument: keylist is null");
1598 retvm_if (keylist->num != 0, VCONF_ERROR,
1599 "Invalid argument: keylist not empty");
1600 retvm_if (dirpath == NULL, VCONF_ERROR,
1601 "Invalid argument: dirpath is null");
1602 retvm_if (_check_keyname_ (dirpath) == 0, VCONF_ERROR,
1603 "Invalid argument: dirpath is not valid");
1605 status = _open_buxton_ ();
1608 ERR ("Can't connect to buxton");
1612 data.keylist = keylist;
1617 data.want_directories = 0;
1619 data.is_recursive = 0;
1622 data.want_directories = 1;
1624 data.is_recursive = 0;
1627 data.want_directories = 1;
1629 data.is_recursive = 0;
1631 case VCONF_GET_KEY_REC:
1632 data.want_directories = 0;
1634 data.is_recursive = 1;
1636 case VCONF_GET_ALL_REC:
1637 data.want_directories = 1;
1639 data.is_recursive = 1;
1641 case VCONF_GET_DIR_REC:
1642 data.want_directories = 0;
1644 data.is_recursive = 1;
1647 ERR ("Invalid argument: Bad option value");
1651 data.dirlen = strlen (dirpath);
1652 assert (data.dirlen);
1653 if (dirpath[data.dirlen - 1] == '/')
1655 data.directory = dirpath;
1660 status = asprintf (&dircopy, "%s/", dirpath);
1661 retvm_if (status < 0, VCONF_ERROR,
1662 "No more memory for copying dirpath");
1663 data.directory = dircopy;
1667 status = _get_layer_key_ (data.directory, &laykey);
1668 if (status != VCONF_OK)
1673 data.prefix = laykey.prefix;
1680 assert (_buxton_ () != NULL);
1681 status = buxton_list_names (_buxton_ (), laykey.layer, default_group,
1682 laykey.key, (BuxtonCallback) _cb_scan_,
1685 status = _wait_buxton_response_ (&data.pending);
1689 retvm_if (status, VCONF_ERROR, "Error while calling buxton_list_names: %m");
1690 if (data.cb_status != VCONF_OK)
1695 return vconf_refresh (keylist);
1699 vconf_get (keylist_t * keylist, const char *dirpath, get_option_t option)
1701 if (option == VCONF_REFRESH_ONLY
1702 || (option == VCONF_GET_KEY && keylist->num != 0))
1704 return vconf_refresh (keylist);
1708 return vconf_scan (keylist, dirpath, option);
1713 vconf_unset (const char *keyname)
1715 struct singleton single;
1718 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1720 status = _keylist_init_singleton_ (&single, keyname, type_delete);
1721 if (status == VCONF_OK)
1723 status = vconf_set (&single.list);
1730 vconf_exists (const char *keyname)
1732 struct singleton single;
1735 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1737 status = _keylist_init_singleton_ (&single, keyname, type_unset);
1738 if (status == VCONF_OK)
1740 status = vconf_refresh (&single.list);
1741 if (status == VCONF_OK && single.node.type == type_string)
1742 free (single.node.value.s);
1749 vconf_unset_recursive (const char *in_dir)
1751 struct _keylist_t *keylist;
1752 struct _keynode_t *keynode;
1755 retvm_if (in_dir == NULL, VCONF_ERROR, "Invalid argument: dir is null");
1757 keylist = vconf_keylist_new ();
1758 if (keylist == NULL)
1761 status = vconf_scan (keylist, in_dir, VCONF_GET_KEY_REC);
1762 if (status == VCONF_OK)
1764 for (keynode = keylist->head; keynode; keynode = keynode->next)
1765 keynode->type = type_delete;
1766 status = vconf_set (keylist);
1768 vconf_keylist_free (keylist);
1773 vconf_notify_key_changed (const char *keyname, vconf_callback_fn cb,
1777 struct notify *notif;
1778 keynode_t *keynode, *aknode;
1781 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null");
1782 retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
1783 status = _open_buxton_ ();
1784 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1785 status = vconf_exists (keyname);
1786 retvm_if (status != VCONF_OK, VCONF_ERROR, "key %s doesn't exist", keyname);
1790 * create the notification
1792 notif = malloc (sizeof *notif);
1793 retvm_if (notif == NULL, VCONF_ERROR,
1794 "Allocation of notify structure failed");
1797 * ensure existing list
1800 if (notify_keylist == NULL)
1802 notify_keylist = vconf_keylist_new ();
1803 if (notify_keylist == NULL)
1812 * search keynode of keyname
1814 keynode = _keylist_lookup_ (notify_keylist, keyname, NULL);
1815 if (keynode == NULL)
1818 * not found, create it with type unset
1820 keynode = _keylist_add_ (notify_keylist, keyname, type_unset);
1821 if (keynode == NULL)
1830 * init the notification
1832 notif->callback = cb;
1833 notif->userdata = user_data;
1834 notif->keynode = keynode;
1835 notif->next = notify_entries;
1836 notify_entries = notif;
1840 * record the notification
1842 status = _notify_reg_unreg_ (notif, true);
1843 if (status != VCONF_OK)
1845 vconf_ignore_key_changed (keyname, cb);
1849 #if !defined(NO_GLIB)
1850 return _glib_start_watch_ ();
1857 vconf_ignore_key_changed (const char *keyname, vconf_callback_fn cb)
1859 struct notify *entry, **prevent, *delent, **prevdelent;
1860 keynode_t *keynode, **prevnod;
1864 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null");
1865 retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
1866 status = _open_buxton_ ();
1867 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1870 status = VCONF_ERROR;
1874 if (notify_keylist != NULL)
1876 keynode = _keylist_lookup_ (notify_keylist, keyname, &prevnod);
1877 if (keynode != NULL)
1879 prevdelent = &delent;
1880 prevent = ¬ify_entries;
1881 entry = notify_entries;
1882 while (entry != NULL)
1884 if (entry->keynode == keynode)
1886 if (entry->callback == cb)
1888 *prevdelent = entry;
1889 prevdelent = &entry->next;
1890 entry = entry->next;
1896 prevent = &entry->next;
1897 entry = entry->next;
1902 *prevnod = keynode->next;
1903 #if !defined(NO_GLIB)
1904 if (notify_entries == NULL)
1905 _glib_stop_watch_ ();
1910 while (delent != NULL)
1913 delent = entry->next;
1914 _notify_reg_unreg_ (entry, false);
1918 _keynode_free_ (keynode);
1924 ERR ("Not found: can't remove notification for key(%s)", keyname);
1930 vconf_set_int (const char *keyname, const int intval)
1932 struct singleton single;
1935 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1937 status = _keylist_init_singleton_ (&single, keyname, type_int);
1938 if (status == VCONF_OK)
1940 single.node.value.i = intval;
1941 status = vconf_set (&single.list);
1947 vconf_set_bool (const char *keyname, const int boolval)
1949 struct singleton single;
1952 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1954 status = _keylist_init_singleton_ (&single, keyname, type_bool);
1955 if (status == VCONF_OK)
1957 single.node.value.b = (bool) boolval;
1958 status = vconf_set (&single.list);
1964 vconf_set_dbl (const char *keyname, const double dblval)
1966 struct singleton single;
1969 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1971 status = _keylist_init_singleton_ (&single, keyname, type_double);
1972 if (status == VCONF_OK)
1974 single.node.value.d = dblval;
1975 status = vconf_set (&single.list);
1981 vconf_set_str (const char *keyname, const char *strval)
1983 struct singleton single;
1986 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1988 status = _keylist_init_singleton_ (&single, keyname, type_string);
1989 if (status == VCONF_OK)
1991 single.node.value.s = (char *) strval;
1992 status = vconf_set (&single.list);
1998 vconf_get_int (const char *keyname, int *intval)
2000 struct singleton single;
2003 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2005 status = _keylist_init_singleton_ (&single, keyname, type_int);
2006 if (status == VCONF_OK)
2008 status = vconf_refresh (&single.list);
2009 if (status == VCONF_OK)
2010 *intval = single.node.value.i;
2016 vconf_set_label (const char *keyname, const char *label)
2018 struct singleton single;
2021 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2023 retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL");
2025 status = _keylist_init_singleton_ (&single, keyname, type_unset);
2026 if (status == VCONF_OK)
2028 status = vconf_set_labels (&single.list, label);
2034 vconf_get_bool (const char *keyname, int *boolval)
2036 struct singleton single;
2039 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2041 status = _keylist_init_singleton_ (&single, keyname, type_bool);
2042 if (status == VCONF_OK)
2044 status = vconf_refresh (&single.list);
2045 if (status == VCONF_OK)
2046 *boolval = (int) single.node.value.b;
2052 vconf_get_dbl (const char *keyname, double *dblval)
2054 struct singleton single;
2057 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2059 status = _keylist_init_singleton_ (&single, keyname, type_double);
2060 if (status == VCONF_OK)
2062 status = vconf_refresh (&single.list);
2063 if (status == VCONF_OK)
2064 *dblval = single.node.value.d;
2070 vconf_get_str (const char *keyname)
2072 struct singleton single;
2075 retvm_if (keyname == NULL, NULL, "Invalid argument: key is NULL");
2077 status = _keylist_init_singleton_ (&single, keyname, type_string);
2078 if (status != VCONF_OK)
2081 single.node.value.s = NULL;
2082 status = vconf_refresh (&single.list);
2083 if (status != VCONF_OK)
2086 return single.node.value.s;