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");
537 _dispatch_buxton_ (int writing, int lock)
542 assert (_buxton_ () != NULL);
544 pfd.fd = the_buxton_client_fd;
545 pfd.events = writing ? POLLIN | POLLOUT : POLLIN;
549 status = poll (&pfd, 1, default_timeout);
557 else if (status == 1)
559 if (pfd.revents & POLLIN)
561 status = _handle_buxton_response_ (lock);
571 if (pfd.revents & POLLOUT)
584 _wait_buxton_response_ (int *pending)
590 result = _dispatch_buxton_ (0, 1);
592 while (result == VCONF_OK && *pending);
597 _get_layer_key_ (const char *keyname, struct layer_key *laykey)
606 prefix = assoc_prefix_layer[i][0];
607 while (prefix != NULL)
609 for (j = 0; prefix[j] && prefix[j] == keyname[j]; j++);
610 if (!prefix[j] && (!keyname[j] || keyname[j] == '/'))
612 laykey->prefix = prefix;
613 laykey->layer = assoc_prefix_layer[i][1];
614 #if defined(REMOVE_PREFIXES)
615 laykey->key = keyname + j + (keyname[j] == '/');
617 laykey->key = keyname;
622 prefix = assoc_prefix_layer[i][0];
624 ERR ("Invalid argument: wrong prefix of key(%s)", keyname);
628 static inline BuxtonKey
629 _get_buxton_key_ (keynode_t * node)
632 struct layer_key laykey;
637 if (_get_layer_key_ (node->keyname, &laykey) != VCONF_OK)
648 type = BUXTON_TYPE_STRING;
651 type = BUXTON_TYPE_INT32;
654 type = BUXTON_TYPE_DOUBLE;
657 type = BUXTON_TYPE_BOOLEAN;
660 type = BUXTON_TYPE_UNSET;
663 return buxton_key_create (default_group, laykey.key, laykey.layer, type);
666 /*================= SECTION set/unset/refresh =============*/
669 _cb_inc_received_ (BuxtonResponse resp, keynode_t * keynode)
673 assert (keynode != NULL);
674 assert (keynode->list != NULL);
676 list = keynode->list;
678 if (buxton_response_status (resp) != 0)
680 ERR ("Buxton returned error %d for key %s",
681 buxton_response_status (resp), keynode->keyname);
682 list->cb_status = VCONF_ERROR;
687 _set_response_to_keynode_ (BuxtonResponse resp, keynode_t * keynode,
691 BuxtonDataType buxtyp;
694 assert (keynode != NULL);
695 assert (buxton_response_status (resp) == 0);
697 buxtyp = buxton_response_value_type (resp);
700 case BUXTON_TYPE_STRING:
703 case BUXTON_TYPE_INT32:
706 case BUXTON_TYPE_DOUBLE:
709 case BUXTON_TYPE_BOOLEAN:
716 if (force && type != keynode->type && keynode->type != type_unset)
719 buxval = buxton_response_value (resp);
723 if (keynode->type == type_string)
724 free (keynode->value.s);
726 keynode->type = type;
730 keynode->value.s = buxval;
733 keynode->value.i = (int) *(int32_t *) buxval;
736 keynode->value.d = *(double *) buxval;
739 keynode->value.b = *(bool *) buxval;
750 _cb_refresh_ (BuxtonResponse resp, keynode_t * keynode)
754 assert (keynode != NULL);
755 assert (keynode->list != NULL);
756 assert (buxton_response_type (resp) == BUXTON_CONTROL_GET);
758 list = keynode->list;
760 if (buxton_response_status (resp) != 0)
762 ERR ("Error %d while getting buxton key %s",
763 buxton_response_status (resp), keynode->keyname);
764 list->cb_status = VCONF_ERROR;
766 else if (_set_response_to_keynode_ (resp, keynode, 0) != VCONF_OK)
768 list->cb_status = VCONF_ERROR;
773 _cb_scan_ (BuxtonResponse resp, struct scanning_data *data)
787 * check the response status
789 if (buxton_response_status (resp) != 0)
791 ERR ("Error while getting list of names from buxton");
792 data->cb_status = VCONF_ERROR;
797 * iterate on the list of names
799 assert (data->directory[data->dirlen - 1] == '/');
800 keylist = data->keylist;
801 count = buxton_response_list_names_count (resp);
803 while (index < count)
808 buxname = buxton_response_list_names_item (resp, index++);
811 ERR ("Unexpected NULL name returned by buxton");
812 data->cb_status = VCONF_ERROR;
819 #if defined(REMOVE_PREFIXES)
820 length = asprintf (&name, "%s/%s", data->prefix, buxname);
822 length = asprintf (&name, "%s", buxname);
827 ERR ("Memory allocation error");
828 data->cb_status = VCONF_ERROR;
831 assert (_check_keyname_ (name));
832 assert (!memcmp (data->directory, name, data->dirlen));
835 * add key if requested
837 term = strchr (name + data->dirlen, '/');
838 if (data->want_keys && (data->is_recursive || term == NULL))
840 keynode = _keylist_getadd_ (keylist, name, type_unset);
844 data->cb_status = VCONF_ERROR;
850 * add directories if requested
852 if (data->want_directories)
857 keynode = _keylist_getadd_ (keylist, name, type_directory);
861 data->cb_status = VCONF_ERROR;
864 if (!data->is_recursive)
869 term = strchr (term + 1, '/');
875 data->cb_status = VCONF_OK;
880 _async_set_ (keynode_t * keynode)
886 assert (keynode != NULL);
888 switch (keynode->type)
891 data = keynode->value.s;
896 data = &keynode->value;
902 key = _get_buxton_key_ (keynode);
908 status = buxton_set_value (_buxton_ (), key,
910 (BuxtonCallback) _cb_inc_received_, keynode,
912 buxton_key_free (key);
919 ERR ("Error while calling buxton_set_value: %m");
924 _async_unset_ (keynode_t * keynode)
929 assert (keynode != NULL);
931 if (keynode->type != type_delete)
936 key = _get_buxton_key_ (keynode);
942 status = buxton_unset_value (_buxton_ (), key,
943 (BuxtonCallback) _cb_inc_received_,
945 buxton_key_free (key);
952 ERR ("Error while calling buxton_unset_value: %m");
957 _async_set_or_unset_ (keynode_t * keynode, const char *unused)
959 assert (keynode != NULL);
961 switch (keynode->type)
967 return _async_unset_ (keynode);
969 return _async_set_ (keynode);
974 _async_refresh_ (keynode_t * keynode, const char *unused)
979 assert (keynode != NULL);
981 switch (keynode->type)
993 key = _get_buxton_key_ (keynode);
999 status = buxton_get_value (_buxton_ (), key,
1000 (BuxtonCallback) _cb_refresh_, keynode, false);
1001 buxton_key_free (key);
1008 ERR ("Error while calling buxton_get_value: %m");
1013 _async_set_label_ (keynode_t * keynode, const char *label)
1018 assert (keynode != NULL);
1020 key = _get_buxton_key_ (keynode);
1026 status = buxton_set_label (_buxton_ (), key, label,
1027 (BuxtonCallback) _cb_inc_received_,
1029 buxton_key_free (key);
1036 ERR ("Error while calling buxton_set_label: %m");
1042 _apply_buxton_on_list_ (keylist_t * keylist,
1043 int (*async) (keynode_t *, const char *),
1050 assert (keylist != NULL);
1052 status = _open_buxton_ ();
1053 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1054 assert (_buxton_ () != NULL);
1056 retvm_if (keylist->cb_active != 0, VCONF_ERROR,
1057 "Already active in vconf-buxton");
1061 keylist->cb_active = 1;
1062 keylist->cb_status = VCONF_OK;
1063 keylist->cb_sent = 0;
1064 keylist->cb_received = 0;
1066 keynode = keylist->head;
1067 status = _dispatch_buxton_ (1, 0);
1068 while (keynode != NULL && status == VCONF_OK)
1070 sent = async (keynode, data);
1071 keynode = keynode->next;
1074 status = VCONF_ERROR;
1078 keylist->cb_sent += sent;
1079 status = _dispatch_buxton_ (1, 0);
1086 while (status == VCONF_OK && keylist->cb_sent != keylist->cb_received)
1088 status = _dispatch_buxton_ (0, 0);
1091 if (status == VCONF_OK && keylist->cb_status != VCONF_OK)
1092 status = keylist->cb_status;
1093 keylist->cb_active = 0;
1097 _check_close_buxton_ ();
1102 /*================= SECTION notification =============*/
1105 _cb_notify_ (BuxtonResponse resp, struct notify *notif)
1107 switch (buxton_response_type (resp))
1109 case BUXTON_CONTROL_NOTIFY:
1110 case BUXTON_CONTROL_UNNOTIFY:
1112 buxton_response_status (resp) == 0 ? VCONF_OK : VCONF_ERROR;
1114 case BUXTON_CONTROL_CHANGED:
1115 if (_set_response_to_keynode_ (resp, notif->keynode, 1) == VCONF_OK)
1118 notif->callback (notif->keynode, notif->userdata);
1128 _notify_reg_unreg_ (struct notify *notif, bool reg)
1133 status = _open_buxton_ ();
1134 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1137 key = _get_buxton_key_ (notif->keynode);
1138 retvm_if (key == NULL, VCONF_ERROR, "Can't create buxton key");
1139 notif->status = VCONF_OK; /* on success calback isn't called! */
1141 (reg ? buxton_register_notification :
1142 buxton_unregister_notification) (_buxton_ (), key,
1143 (BuxtonCallback) _cb_notify_,
1145 buxton_key_free (key);
1147 return status == 0 && notif->status == VCONF_OK ? VCONF_OK : VCONF_ERROR;
1150 #if !defined(NO_GLIB)
1151 /*================= SECTION glib =============*/
1154 _cb_glib_ (GIOChannel * src, GIOCondition cond, gpointer data)
1156 _handle_buxton_response_ (1);
1157 return G_SOURCE_CONTINUE;
1161 _glib_start_watch_ ()
1165 if (glib_source != NULL)
1168 gio = g_io_channel_unix_new (the_buxton_client_fd);
1169 retvm_if (gio == NULL, VCONF_ERROR, "Error: create a new GIOChannel");
1171 g_io_channel_set_flags (gio, G_IO_FLAG_NONBLOCK, NULL);
1173 glib_source = g_io_create_watch (gio, G_IO_IN);
1174 if (glib_source == NULL)
1176 ERR ("Error: create a new GSource");
1177 g_io_channel_unref (gio);
1181 g_source_set_callback (glib_source, (GSourceFunc) _cb_glib_, NULL, NULL);
1182 g_source_attach (glib_source, NULL);
1183 g_io_channel_unref (gio);
1184 g_source_unref (glib_source);
1190 _glib_stop_watch_ ()
1192 if (glib_source != NULL)
1194 g_source_destroy (glib_source);
1200 /*================= SECTION VCONF API =============*/
1203 vconf_keynode_get_name (keynode_t * keynode)
1205 retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL");
1206 retvm_if (keynode->keyname == NULL, NULL, "The name of keynode is NULL");
1208 return keynode->keyname;
1212 vconf_keynode_get_type (keynode_t * keynode)
1214 retvm_if (keynode == NULL,
1215 VCONF_ERROR, "Invalid argument: keynode is NULL");
1217 switch (keynode->type)
1219 case type_directory:
1220 return VCONF_TYPE_DIR;
1222 return VCONF_TYPE_STRING;
1224 return VCONF_TYPE_INT;
1226 return VCONF_TYPE_DOUBLE;
1228 return VCONF_TYPE_BOOL;
1230 return VCONF_TYPE_NONE;
1235 vconf_keynode_get_int (keynode_t * keynode)
1237 retvm_if (keynode == NULL,
1238 VCONF_ERROR, "Invalid argument: keynode is NULL");
1239 retvm_if (keynode->type != type_int, VCONF_ERROR,
1240 "The type of keynode(%s) is not INT", keynode->keyname);
1242 return keynode->value.i;
1246 vconf_keynode_get_dbl (keynode_t * keynode)
1248 retvm_if (keynode == NULL, -1.0, "Invalid argument: keynode is NULL");
1249 retvm_if (keynode->type != type_double, -1.0,
1250 "The type of keynode(%s) is not DBL", keynode->keyname);
1252 return keynode->value.d;
1256 vconf_keynode_get_bool (keynode_t * keynode)
1258 retvm_if (keynode == NULL,
1259 VCONF_ERROR, "Invalid argument: keynode is NULL");
1260 retvm_if (keynode->type != type_bool, VCONF_ERROR,
1261 "The type of keynode(%s) is not BOOL", keynode->keyname);
1263 return !!(keynode->value.b);
1267 vconf_keynode_get_str (keynode_t * keynode)
1269 retvm_if (keynode == NULL, NULL, "Invalid argument: keynode is NULL");
1270 retvm_if (keynode->type != type_string, NULL,
1271 "The type of keynode(%s) is not STR", keynode->keyname);
1273 return keynode->value.s;
1277 vconf_set_default_group (const char *groupname)
1281 copy = _dup_groupname_ (groupname);
1284 free (default_group);
1285 default_group = copy;
1290 vconf_keylist_new ()
1293 if (_ensure_default_group_ () != VCONF_OK)
1295 result = calloc (1, sizeof (keylist_t));
1297 internal_list_count += (result != NULL);
1303 vconf_keylist_free (keylist_t * keylist)
1305 keynode_t *keynode, *temp;
1307 retvm_if (keylist == NULL,
1308 VCONF_ERROR, "Invalid argument: keylist is NULL");
1310 keynode = keylist->head;
1314 temp = keynode->next;
1315 _keynode_free_ (keynode);
1320 internal_list_count -= (internal_list_count > 0);
1322 _check_close_buxton_ ();
1327 vconf_keylist_rewind (keylist_t * keylist)
1329 retvm_if (keylist == NULL,
1330 VCONF_ERROR, "Invalid argument: keylist is NULL");
1332 keylist->cursor = NULL;
1338 vconf_keylist_nextnode (keylist_t * keylist)
1342 retvm_if (keylist == NULL, NULL, "Invalid argument: keylist is NULL");
1344 result = keylist->cursor;
1345 result = result == NULL ? keylist->head : result->next;
1346 keylist->cursor = result;
1352 vconf_keylist_lookup (keylist_t * keylist,
1353 const char *keyname, keynode_t ** return_node)
1357 retvm_if (keylist == NULL,
1358 VCONF_ERROR, "Invalid argument: keylist is NULL");
1359 retvm_if (keyname == NULL,
1360 VCONF_ERROR, "Invalid argument: keyname is NULL");
1361 retvm_if (return_node == NULL,
1362 VCONF_ERROR, "Invalid argument: return_node is NULL");
1364 keynode = _keylist_lookup_ (keylist, keyname, NULL);
1365 if (NULL == keynode)
1369 *return_node = keynode;
1370 return keynode->type;
1374 _cb_sort_keynodes (const void *a, const void *b)
1376 register const keynode_t *kna = *(const keynode_t **) a;
1377 register const keynode_t *knb = *(const keynode_t **) b;
1378 return strcmp (kna->keyname, knb->keyname);
1382 vconf_keylist_sort (keylist_t * keylist)
1385 keynode_t **nodes, *keynode;
1387 retvm_if (keylist == NULL,
1388 VCONF_ERROR, "Invalid argument: keylist is NULL");
1390 if (keylist->num <= 1)
1393 nodes = malloc (keylist->num * sizeof *nodes);
1394 retvm_if (nodes == NULL, VCONF_ERROR, "can't allocate memory for sorting");
1397 keynode = keylist->head;
1398 while (keynode != NULL)
1400 assert (index < keylist->num);
1401 nodes[index++] = keynode;
1402 keynode = keynode->next;
1404 assert (index == keylist->num);
1406 qsort (nodes, index, sizeof *nodes, _cb_sort_keynodes);
1410 nodes[--index]->next = keynode;
1411 keynode = nodes[index];
1413 keylist->head = keynode;
1419 vconf_keylist_add_int (keylist_t * keylist, const char *keyname,
1424 retvm_if (keylist == NULL,
1425 VCONF_ERROR, "Invalid argument: keylist is NULL");
1426 retvm_if (keyname == NULL,
1427 VCONF_ERROR, "Invalid argument: keyname is NULL");
1429 keynode = _keylist_getadd_ (keylist, keyname, type_int);
1430 if (keynode == NULL)
1433 keynode->value.i = value;
1434 return keylist->num;
1438 vconf_keylist_add_bool (keylist_t * keylist, const char *keyname,
1443 retvm_if (keylist == NULL,
1444 VCONF_ERROR, "Invalid argument: keylist is NULL");
1445 retvm_if (keyname == NULL,
1446 VCONF_ERROR, "Invalid argument: keyname is NULL");
1448 keynode = _keylist_getadd_ (keylist, keyname, type_bool);
1449 if (keynode == NULL)
1452 keynode->value.b = !!value;
1453 return keylist->num;
1457 vconf_keylist_add_dbl (keylist_t * keylist,
1458 const char *keyname, const double value)
1462 retvm_if (keylist == NULL, VCONF_ERROR,
1463 "Invalid argument: keylist is NULL");
1464 retvm_if (keyname == NULL, VCONF_ERROR,
1465 "Invalid argument: keyname is NULL");
1467 keynode = _keylist_getadd_ (keylist, keyname, type_double);
1468 if (keynode == NULL)
1471 keynode->value.d = value;
1472 return keylist->num;
1476 vconf_keylist_add_str (keylist_t * keylist,
1477 const char *keyname, const char *value)
1482 retvm_if (keylist == NULL, VCONF_ERROR,
1483 "Invalid argument: keylist is NULL");
1484 retvm_if (keyname == NULL, VCONF_ERROR,
1485 "Invalid argument: keyname is NULL");
1487 copy = strdup (value == NULL ? "" : value);
1488 retvm_if (copy == NULL, VCONF_ERROR, "Allocation of memory failed");
1490 keynode = _keylist_getadd_ (keylist, keyname, type_string);
1491 if (keynode == NULL)
1497 free (keynode->value.s);
1498 keynode->value.s = copy;
1499 return keylist->num;
1503 vconf_keylist_add_null (keylist_t * keylist, const char *keyname)
1507 retvm_if (keylist == NULL, VCONF_ERROR,
1508 "Invalid argument: keylist is NULL");
1509 retvm_if (keyname == NULL, VCONF_ERROR,
1510 "Invalid argument: keyname is NULL");
1512 keynode = _keylist_getadd_ (keylist, keyname, type_unset);
1513 if (keynode == NULL)
1516 return keylist->num;
1520 vconf_keylist_del (keylist_t * keylist, const char *keyname)
1522 keynode_t *keynode, **previous = NULL;
1524 retvm_if (keylist == NULL, VCONF_ERROR,
1525 "Invalid argument: keylist is NULL");
1526 retvm_if (keyname == NULL, VCONF_ERROR,
1527 "Invalid argument: keyname is NULL");
1529 keynode = _keylist_lookup_ (keylist, keyname, &previous);
1530 if (keynode == NULL)
1533 *previous = keynode->next;
1535 _keynode_free_ (keynode);
1541 vconf_set (keylist_t * keylist)
1543 retvm_if (keylist == NULL, VCONF_ERROR,
1544 "Invalid argument: keylist is NULL");
1546 return _apply_buxton_on_list_ (keylist, _async_set_or_unset_, NULL);
1550 vconf_set_labels (keylist_t * keylist, const char *label)
1552 retvm_if (keylist == NULL, VCONF_ERROR,
1553 "Invalid argument: keylist is NULL");
1555 retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL");
1557 return _apply_buxton_on_list_ (keylist, _async_set_label_, label);
1561 vconf_sync_key (const char *keyname)
1564 * does nothing succefully
1570 vconf_refresh (keylist_t * keylist)
1572 retvm_if (keylist == NULL, VCONF_ERROR,
1573 "Invalid argument: keylist is NULL");
1575 return _apply_buxton_on_list_ (keylist, _async_refresh_, NULL);
1579 vconf_scan (keylist_t * keylist, const char *dirpath, get_option_t option)
1582 struct layer_key laykey;
1583 struct scanning_data data;
1586 retvm_if (keylist == NULL, VCONF_ERROR,
1587 "Invalid argument: keylist is null");
1588 retvm_if (keylist->num != 0, VCONF_ERROR,
1589 "Invalid argument: keylist not empty");
1590 retvm_if (dirpath == NULL, VCONF_ERROR,
1591 "Invalid argument: dirpath is null");
1592 retvm_if (_check_keyname_ (dirpath) == 0, VCONF_ERROR,
1593 "Invalid argument: dirpath is not valid");
1595 status = _open_buxton_ ();
1598 ERR ("Can't connect to buxton");
1602 data.keylist = keylist;
1607 data.want_directories = 0;
1609 data.is_recursive = 0;
1612 data.want_directories = 1;
1614 data.is_recursive = 0;
1617 data.want_directories = 1;
1619 data.is_recursive = 0;
1621 case VCONF_GET_KEY_REC:
1622 data.want_directories = 0;
1624 data.is_recursive = 1;
1626 case VCONF_GET_ALL_REC:
1627 data.want_directories = 1;
1629 data.is_recursive = 1;
1631 case VCONF_GET_DIR_REC:
1632 data.want_directories = 0;
1634 data.is_recursive = 1;
1637 ERR ("Invalid argument: Bad option value");
1641 data.dirlen = strlen (dirpath);
1642 assert (data.dirlen);
1643 if (dirpath[data.dirlen - 1] == '/')
1645 data.directory = dirpath;
1650 status = asprintf (&dircopy, "%s/", dirpath);
1651 retvm_if (status < 0, VCONF_ERROR,
1652 "No more memory for copying dirpath");
1653 data.directory = dircopy;
1657 status = _get_layer_key_ (data.directory, &laykey);
1658 if (status != VCONF_OK)
1663 data.prefix = laykey.prefix;
1670 assert (_buxton_ () != NULL);
1671 status = buxton_list_names (_buxton_ (), laykey.layer, default_group,
1672 laykey.key, (BuxtonCallback) _cb_scan_,
1675 status = _wait_buxton_response_ (&data.pending);
1679 retvm_if (status, VCONF_ERROR, "Error while calling buxton_list_names: %m");
1680 if (data.cb_status != VCONF_OK)
1685 return vconf_refresh (keylist);
1689 vconf_get (keylist_t * keylist, const char *dirpath, get_option_t option)
1691 if (option == VCONF_REFRESH_ONLY
1692 || (option == VCONF_GET_KEY && keylist->num != 0))
1694 return vconf_refresh (keylist);
1698 return vconf_scan (keylist, dirpath, option);
1703 vconf_unset (const char *keyname)
1705 struct singleton single;
1708 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1710 status = _keylist_init_singleton_ (&single, keyname, type_delete);
1711 if (status == VCONF_OK)
1713 status = vconf_set (&single.list);
1720 vconf_exists (const char *keyname)
1722 struct singleton single;
1725 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1727 status = _keylist_init_singleton_ (&single, keyname, type_unset);
1728 if (status == VCONF_OK)
1730 status = vconf_refresh (&single.list);
1731 if (status == VCONF_OK && single.node.type == type_string)
1732 free (single.node.value.s);
1739 vconf_unset_recursive (const char *in_dir)
1741 struct _keylist_t *keylist;
1742 struct _keynode_t *keynode;
1745 retvm_if (in_dir == NULL, VCONF_ERROR, "Invalid argument: dir is null");
1747 keylist = vconf_keylist_new ();
1748 if (keylist == NULL)
1751 status = vconf_scan (keylist, in_dir, VCONF_GET_KEY_REC);
1752 if (status == VCONF_OK)
1754 for (keynode = keylist->head; keynode; keynode = keynode->next)
1755 keynode->type = type_delete;
1756 status = vconf_set (keylist);
1758 vconf_keylist_free (keylist);
1763 vconf_notify_key_changed (const char *keyname, vconf_callback_fn cb,
1767 struct notify *notif;
1768 keynode_t *keynode, *aknode;
1771 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null");
1772 retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
1773 status = _open_buxton_ ();
1774 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1775 status = vconf_exists (keyname);
1776 retvm_if (status != VCONF_OK, VCONF_ERROR, "key %s doesn't exist", keyname);
1780 * create the notification
1782 notif = malloc (sizeof *notif);
1783 retvm_if (notif == NULL, VCONF_ERROR,
1784 "Allocation of notify structure failed");
1787 * ensure existing list
1790 if (notify_keylist == NULL)
1792 notify_keylist = vconf_keylist_new ();
1793 if (notify_keylist == NULL)
1802 * search keynode of keyname
1804 keynode = _keylist_lookup_ (notify_keylist, keyname, NULL);
1805 if (keynode == NULL)
1808 * not found, create it with type unset
1810 keynode = _keylist_add_ (notify_keylist, keyname, type_unset);
1811 if (keynode == NULL)
1820 * init the notification
1822 notif->callback = cb;
1823 notif->userdata = user_data;
1824 notif->keynode = keynode;
1825 notif->next = notify_entries;
1826 notify_entries = notif;
1830 * record the notification
1832 status = _notify_reg_unreg_ (notif, true);
1833 if (status != VCONF_OK)
1835 vconf_ignore_key_changed (keyname, cb);
1839 #if !defined(NO_GLIB)
1840 return _glib_start_watch_ ();
1847 vconf_ignore_key_changed (const char *keyname, vconf_callback_fn cb)
1849 struct notify *entry, **prevent, *delent, **prevdelent;
1850 keynode_t *keynode, **prevnod;
1854 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is null");
1855 retvm_if (cb == NULL, VCONF_ERROR, "Invalid argument: cb(%p)", cb);
1856 status = _open_buxton_ ();
1857 retvm_if (!status, VCONF_ERROR, "Can't connect to buxton");
1860 status = VCONF_ERROR;
1864 if (notify_keylist != NULL)
1866 keynode = _keylist_lookup_ (notify_keylist, keyname, &prevnod);
1867 if (keynode != NULL)
1869 prevdelent = &delent;
1870 prevent = ¬ify_entries;
1871 entry = notify_entries;
1872 while (entry != NULL)
1874 if (entry->keynode == keynode)
1876 if (entry->callback == cb)
1878 *prevdelent = entry;
1879 prevdelent = &entry->next;
1880 entry = entry->next;
1886 prevent = &entry->next;
1887 entry = entry->next;
1892 *prevnod = keynode->next;
1893 #if !defined(NO_GLIB)
1894 if (notify_entries == NULL)
1895 _glib_stop_watch_ ();
1900 while (delent != NULL)
1903 delent = entry->next;
1904 _notify_reg_unreg_ (entry, false);
1908 _keynode_free_ (keynode);
1914 ERR ("Not found: can't remove notification for key(%s)", keyname);
1920 vconf_set_int (const char *keyname, const int intval)
1922 struct singleton single;
1925 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1927 status = _keylist_init_singleton_ (&single, keyname, type_int);
1928 if (status == VCONF_OK)
1930 single.node.value.i = intval;
1931 status = vconf_set (&single.list);
1937 vconf_set_bool (const char *keyname, const int boolval)
1939 struct singleton single;
1942 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1944 status = _keylist_init_singleton_ (&single, keyname, type_bool);
1945 if (status == VCONF_OK)
1947 single.node.value.b = (bool) boolval;
1948 status = vconf_set (&single.list);
1954 vconf_set_dbl (const char *keyname, const double dblval)
1956 struct singleton single;
1959 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1961 status = _keylist_init_singleton_ (&single, keyname, type_double);
1962 if (status == VCONF_OK)
1964 single.node.value.d = dblval;
1965 status = vconf_set (&single.list);
1971 vconf_set_str (const char *keyname, const char *strval)
1973 struct singleton single;
1976 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1978 status = _keylist_init_singleton_ (&single, keyname, type_string);
1979 if (status == VCONF_OK)
1981 single.node.value.s = (char *) strval;
1982 status = vconf_set (&single.list);
1988 vconf_get_int (const char *keyname, int *intval)
1990 struct singleton single;
1993 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
1995 status = _keylist_init_singleton_ (&single, keyname, type_int);
1996 if (status == VCONF_OK)
1998 status = vconf_refresh (&single.list);
1999 if (status == VCONF_OK)
2000 *intval = single.node.value.i;
2006 vconf_set_label (const char *keyname, const char *label)
2008 struct singleton single;
2011 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2013 retvm_if (label == NULL, VCONF_ERROR, "Invalid argument: name is NULL");
2015 status = _keylist_init_singleton_ (&single, keyname, type_unset);
2016 if (status == VCONF_OK)
2018 status = vconf_set_labels (&single.list, label);
2024 vconf_get_bool (const char *keyname, int *boolval)
2026 struct singleton single;
2029 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2031 status = _keylist_init_singleton_ (&single, keyname, type_bool);
2032 if (status == VCONF_OK)
2034 status = vconf_refresh (&single.list);
2035 if (status == VCONF_OK)
2036 *boolval = (int) single.node.value.b;
2042 vconf_get_dbl (const char *keyname, double *dblval)
2044 struct singleton single;
2047 retvm_if (keyname == NULL, VCONF_ERROR, "Invalid argument: key is NULL");
2049 status = _keylist_init_singleton_ (&single, keyname, type_double);
2050 if (status == VCONF_OK)
2052 status = vconf_refresh (&single.list);
2053 if (status == VCONF_OK)
2054 *dblval = single.node.value.d;
2060 vconf_get_str (const char *keyname)
2062 struct singleton single;
2065 retvm_if (keyname == NULL, NULL, "Invalid argument: key is NULL");
2067 status = _keylist_init_singleton_ (&single, keyname, type_string);
2068 if (status != VCONF_OK)
2071 single.node.value.s = NULL;
2072 status = vconf_refresh (&single.list);
2073 if (status != VCONF_OK)
2076 return single.node.value.s;