1
2 /* GConf
3 * Copyright (C) 1999, 2000 Red Hat Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include <config.h>
22 #include "gconf-backend.h"
23 #include "gconf-sources.h"
24 #include "gconf-internals.h"
25 #include "gconf-schema.h"
26 #include "gconf.h"
27 #include <string.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <ctype.h>
36
37 static const char * get_address_resource (const char *address);
38
39 /*
40 * Sources
41 */
42
43 GConfSource*
gconf_resolve_address(const gchar * address,GError ** err)44 gconf_resolve_address(const gchar* address, GError** err)
45 {
46 GConfBackend* backend;
47
48 backend = gconf_get_backend(address, err);
49
50 if (backend == NULL)
51 return NULL;
52 else
53 {
54 GConfSource* retval;
55
56 retval = gconf_backend_resolve_address(backend, address, err);
57
58 if (retval == NULL)
59 {
60 gconf_backend_unref(backend);
61 return NULL;
62 }
63 else
64 {
65 retval->backend = backend;
66 retval->address = g_strdup(address);
67
68 /* Leave a ref on the backend, now held by the GConfSource */
69
70 return retval;
71 }
72 }
73 }
74
75 void
gconf_source_free(GConfSource * source)76 gconf_source_free (GConfSource* source)
77 {
78 GConfBackend* backend;
79 gchar* address;
80
81 g_return_if_fail(source != NULL);
82
83 backend = source->backend;
84 address = source->address;
85
86 (*source->backend->vtable.destroy_source)(source);
87
88 /* Remove ref held by the source. */
89 gconf_backend_unref(backend);
90 g_free(address);
91 }
92
93 #define SOURCE_READABLE(source, key, err) \
94 ( ((source)->flags & GCONF_SOURCE_ALL_READABLE) || \
95 ((source)->backend->vtable.readable != NULL && \
96 (*(source)->backend->vtable.readable)((source), (key), (err))) )
97
98 static gboolean
source_is_writable(GConfSource * source,const gchar * key,GError ** err)99 source_is_writable(GConfSource* source, const gchar* key, GError** err)
100 {
101 if ((source->flags & GCONF_SOURCE_NEVER_WRITEABLE) != 0)
102 return FALSE;
103 else if ((source->flags & GCONF_SOURCE_ALL_WRITEABLE) != 0)
104 return TRUE;
105 else if ((source->backend->vtable.writable != NULL) &&
106 (*source->backend->vtable.writable)(source, key, err))
107 return TRUE;
108 else
109 return FALSE;
110 }
111
112 static GConfValue*
gconf_source_query_value(GConfSource * source,const gchar * key,const gchar ** locales,gchar ** schema_name,GError ** err)113 gconf_source_query_value (GConfSource* source,
114 const gchar* key,
115 const gchar** locales,
116 gchar** schema_name,
117 GError** err)
118 {
119 g_return_val_if_fail(source != NULL, NULL);
120 g_return_val_if_fail(key != NULL, NULL);
121 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
122
123 /* note that key validity is unchecked */
124
125 if ( SOURCE_READABLE(source, key, err) )
126 {
127 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
128 return (*source->backend->vtable.query_value)(source, key, locales, schema_name, err);
129 }
130 else
131 return NULL;
132 }
133
134 static GConfMetaInfo*
gconf_source_query_metainfo(GConfSource * source,const gchar * key,GError ** err)135 gconf_source_query_metainfo (GConfSource* source,
136 const gchar* key,
137 GError** err)
138 {
139 g_return_val_if_fail(source != NULL, NULL);
140 g_return_val_if_fail(key != NULL, NULL);
141 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
142
143 /* note that key validity is unchecked */
144
145 if ( SOURCE_READABLE(source, key, err) )
146 {
147 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
148 return (*source->backend->vtable.query_metainfo)(source, key, err);
149 }
150 else
151 return NULL;
152 }
153
154
155 /* return value indicates whether the key was writable */
156 static gboolean
gconf_source_set_value(GConfSource * source,const gchar * key,const GConfValue * value,GError ** err)157 gconf_source_set_value (GConfSource* source,
158 const gchar* key,
159 const GConfValue* value,
160 GError** err)
161 {
162 g_return_val_if_fail(source != NULL, FALSE);
163 g_return_val_if_fail(value != NULL, FALSE);
164 g_return_val_if_fail(key != NULL, FALSE);
165 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
166
167 /* don't check key validity */
168
169 if ( source_is_writable(source, key, err) )
170 {
171 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
172 (*source->backend->vtable.set_value)(source, key, value, err);
173 return TRUE;
174 }
175 else
176 return FALSE;
177 }
178
179 static gboolean
gconf_source_unset_value(GConfSource * source,const gchar * key,const gchar * locale,GError ** err)180 gconf_source_unset_value (GConfSource* source,
181 const gchar* key,
182 const gchar* locale,
183 GError** err)
184 {
185 g_return_val_if_fail (source != NULL, FALSE);
186 g_return_val_if_fail (key != NULL, FALSE);
187 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
188
189 if ( source_is_writable(source, key, err) )
190 {
191 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
192
193 (*source->backend->vtable.unset_value)(source, key, locale, err);
194 return TRUE;
195 }
196 else
197 return FALSE;
198 }
199
200 static GSList*
gconf_source_all_entries(GConfSource * source,const gchar * dir,const gchar ** locales,GError ** err)201 gconf_source_all_entries (GConfSource* source,
202 const gchar* dir,
203 const gchar** locales,
204 GError** err)
205 {
206 g_return_val_if_fail(source != NULL, NULL);
207 g_return_val_if_fail(dir != NULL, NULL);
208 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
209
210 if ( SOURCE_READABLE(source, dir, err) )
211 {
212 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
213 return (*source->backend->vtable.all_entries)(source, dir, locales, err);
214 }
215 else
216 return NULL;
217 }
218
219 static GSList*
gconf_source_all_dirs(GConfSource * source,const gchar * dir,GError ** err)220 gconf_source_all_dirs (GConfSource* source,
221 const gchar* dir,
222 GError** err)
223 {
224 g_return_val_if_fail(source != NULL, NULL);
225 g_return_val_if_fail(dir != NULL, NULL);
226 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
227
228 if ( SOURCE_READABLE(source, dir, err) )
229 {
230 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
231 return (*source->backend->vtable.all_subdirs)(source, dir, err);
232 }
233 else
234 return NULL;
235 }
236
237 static gboolean
gconf_source_dir_exists(GConfSource * source,const gchar * dir,GError ** err)238 gconf_source_dir_exists (GConfSource* source,
239 const gchar* dir,
240 GError** err)
241 {
242 g_return_val_if_fail(source != NULL, FALSE);
243 g_return_val_if_fail(dir != NULL, FALSE);
244 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
245
246 if ( SOURCE_READABLE(source, dir, err) )
247 {
248 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
249 return (*source->backend->vtable.dir_exists)(source, dir, err);
250 }
251 else
252 return FALSE;
253 }
254
255 static void
gconf_source_remove_dir(GConfSource * source,const gchar * dir,GError ** err)256 gconf_source_remove_dir (GConfSource* source,
257 const gchar* dir,
258 GError** err)
259 {
260 g_return_if_fail(source != NULL);
261 g_return_if_fail(dir != NULL);
262 g_return_if_fail(err == NULL || *err == NULL);
263
264 if ( source_is_writable(source, dir, err) )
265 {
266 g_return_if_fail(err == NULL || *err == NULL);
267 (*source->backend->vtable.remove_dir)(source, dir, err);
268 }
269 }
270
271 static gboolean
gconf_source_set_schema(GConfSource * source,const gchar * key,const gchar * schema_key,GError ** err)272 gconf_source_set_schema (GConfSource* source,
273 const gchar* key,
274 const gchar* schema_key,
275 GError** err)
276 {
277 g_return_val_if_fail (source != NULL, FALSE);
278 g_return_val_if_fail (key != NULL, FALSE);
279 g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
280
281 if ( source_is_writable(source, key, err) )
282 {
283 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
284 (*source->backend->vtable.set_schema)(source, key, schema_key, err);
285 return TRUE;
286 }
287 else
288 return FALSE;
289 }
290
291 static gboolean
gconf_source_sync_all(GConfSource * source,GError ** err)292 gconf_source_sync_all (GConfSource* source, GError** err)
293 {
294 return (*source->backend->vtable.sync_all)(source, err);
295 }
296
297 static void
gconf_source_set_notify_func(GConfSource * source,GConfSourceNotifyFunc notify_func,gpointer user_data)298 gconf_source_set_notify_func (GConfSource *source,
299 GConfSourceNotifyFunc notify_func,
300 gpointer user_data)
301 {
302 g_return_if_fail (source != NULL);
303
304 if (source->backend->vtable.set_notify_func)
305 {
306 (*source->backend->vtable.set_notify_func) (source, notify_func, user_data);
307 }
308 }
309
310 static void
gconf_source_add_listener(GConfSource * source,guint id,const gchar * namespace_section)311 gconf_source_add_listener (GConfSource *source,
312 guint id,
313 const gchar *namespace_section)
314 {
315 g_return_if_fail (source != NULL);
316 g_return_if_fail (id > 0);
317
318 if (source->backend->vtable.add_listener)
319 {
320 (*source->backend->vtable.add_listener) (source, id, namespace_section);
321 }
322 }
323
324 static void
gconf_source_remove_listener(GConfSource * source,guint id)325 gconf_source_remove_listener (GConfSource *source,
326 guint id)
327 {
328 g_return_if_fail (source != NULL);
329 g_return_if_fail (id > 0);
330
331 if (source->backend->vtable.remove_listener)
332 {
333 (*source->backend->vtable.remove_listener) (source, id);
334 }
335 }
336
337 /*
338 * Source stacks
339 */
340
341 GConfSources*
gconf_sources_new_from_addresses(GSList * addresses,GError ** err)342 gconf_sources_new_from_addresses(GSList * addresses, GError** err)
343 {
344 GConfSources *sources;
345 GList *sources_list;
346
347 g_return_val_if_fail( (err == NULL) || (*err == NULL), NULL);
348
349 sources_list = NULL;
350 if (addresses != NULL)
351 {
352 GError *last_error = NULL;
353
354 while (addresses != NULL)
355 {
356 GConfSource* source;
357
358 if (last_error)
359 {
360 g_error_free (last_error);
361 last_error = NULL;
362 }
363
364 source = gconf_resolve_address ((const gchar*)addresses->data, &last_error);
365
366 if (source != NULL)
367 {
368 sources_list = g_list_prepend(sources_list, source);
369 g_return_val_if_fail(last_error == NULL, NULL);
370 }
371 else
372 {
373 g_assert(last_error != NULL);
374 gconf_log(GCL_WARNING, _("Failed to load source \"%s\": %s"),
375 (const gchar*)addresses->data, last_error->message);
376 }
377
378 addresses = g_slist_next(addresses);
379 }
380
381 if (sources_list == NULL)
382 {
383 g_assert (last_error != NULL);
384 g_propagate_error (err, last_error);
385 return NULL;
386 }
387
388 if (last_error)
389 {
390 g_error_free(last_error);
391 last_error = NULL;
392 }
393 }
394
395 sources = g_new0 (GConfSources, 1);
396 sources->sources = g_list_reverse (sources_list);
397
398 {
399 GList *tmp;
400 int i;
401
402 i = 0;
403 tmp = sources->sources;
404 while (tmp != NULL)
405 {
406 GConfSource *source = tmp->data;
407
408 if (source->flags & GCONF_SOURCE_ALL_WRITEABLE)
409 {
410 gconf_log (GCL_DEBUG,
411 _("Resolved address \"%s\" to a writable configuration source at position %d"),
412 source->address, i);
413 }
414 else if (source->flags & GCONF_SOURCE_NEVER_WRITEABLE)
415 {
416 gconf_log (GCL_DEBUG,
417 _("Resolved address \"%s\" to a read-only configuration source at position %d"),
418 source->address, i);
419 }
420 else
421 {
422 gconf_log (GCL_DEBUG,
423 _("Resolved address \"%s\" to a partially writable configuration source at position %d"),
424 source->address, i);
425 }
426
427 ++i;
428 tmp = tmp->next;
429 }
430 }
431
432 return sources;
433 }
434
435 GConfSources*
gconf_sources_new_from_source(GConfSource * source)436 gconf_sources_new_from_source (GConfSource* source)
437 {
438 GConfSources* sources;
439
440 sources = g_new0(GConfSources, 1);
441
442 if (source)
443 sources->sources = g_list_append(NULL, source);
444
445 return sources;
446 }
447
448 void
gconf_sources_free(GConfSources * sources)449 gconf_sources_free(GConfSources* sources)
450 {
451 GList* tmp;
452
453 tmp = sources->sources;
454
455 while (tmp != NULL)
456 {
457 gconf_source_free(tmp->data);
458
459 tmp = g_list_next(tmp);
460 }
461
462 g_list_free(sources->sources);
463
464 g_free(sources);
465 }
466
467 void
gconf_sources_clear_cache(GConfSources * sources)468 gconf_sources_clear_cache (GConfSources *sources)
469 {
470 GList* tmp;
471
472 tmp = sources->sources;
473
474 while (tmp != NULL)
475 {
476 GConfSource* source = tmp->data;
477
478 if (source->backend->vtable.clear_cache)
479 (*source->backend->vtable.clear_cache)(source);
480
481 tmp = g_list_next(tmp);
482 }
483 }
484
485 void
gconf_sources_clear_cache_for_sources(GConfSources * sources,GConfSources * affected)486 gconf_sources_clear_cache_for_sources (GConfSources *sources,
487 GConfSources *affected)
488 {
489 GList* tmp;
490
491 tmp = sources->sources;
492
493 while (tmp != NULL)
494 {
495 GConfSource* source = tmp->data;
496 const char *source_resource = get_address_resource (source->address);
497
498 GList* tmp2;
499
500 if (source->backend->vtable.clear_cache == NULL)
501 continue;
502
503 tmp2 = affected->sources;
504
505 while (tmp2 != NULL)
506 {
507 GConfSource* affected_source = tmp2->data;
508
509 if (source->backend == affected_source->backend &&
510 strcmp (source_resource, get_address_resource (affected_source->address)) == 0)
511 {
512 if (source->backend->vtable.clear_cache)
513 (*source->backend->vtable.clear_cache)(source);
514 }
515
516 tmp2 = g_list_next(tmp2);
517 }
518
519 tmp = g_list_next(tmp);
520 }
521 }
522
523 GConfValue*
gconf_sources_query_value(GConfSources * sources,const gchar * key,const gchar ** locales,gboolean use_schema_default,gboolean * value_is_default,gboolean * value_is_writable,gchar ** schema_namep,GError ** err)524 gconf_sources_query_value (GConfSources* sources,
525 const gchar* key,
526 const gchar** locales,
527 gboolean use_schema_default,
528 gboolean* value_is_default,
529 gboolean* value_is_writable,
530 gchar **schema_namep,
531 GError** err)
532 {
533 GList* tmp;
534 gchar* schema_name;
535 GError* error;
536 GConfValue* val;
537
538 g_return_val_if_fail (sources != NULL, NULL);
539 g_return_val_if_fail (key != NULL, NULL);
540 g_return_val_if_fail ((err == NULL) || (*err == NULL), NULL);
541
542 /* A value is writable if it is unset and a writable source exists,
543 * or if it's set and the setting is within or after a writable source.
544 * So basically if we see a writable source before we get the value,
545 * or get the value from a writable source, the value is writable.
546 */
547
548 if (!gconf_key_check(key, err))
549 return NULL;
550
551 if (value_is_default)
552 *value_is_default = FALSE;
553
554 if (value_is_writable)
555 *value_is_writable = FALSE;
556
557 if (schema_namep)
558 *schema_namep = NULL;
559
560 val = NULL;
561 schema_name = NULL;
562 error = NULL;
563
564 tmp = sources->sources;
565
566 while (tmp != NULL)
567 {
568 GConfSource* source;
569 gchar** schema_name_retloc;
570
571 schema_name_retloc = &schema_name;
572 if (schema_name != NULL || /* already have the schema name */
573 (schema_namep == NULL && !use_schema_default)) /* don't need to get the schema name */
574 schema_name_retloc = NULL;
575
576 source = tmp->data;
577
578 if (val == NULL)
579 {
580 /* A key is writable if the source containing its value or
581 * an earlier source is writable
582 */
583 if (value_is_writable &&
584 source_is_writable (source, key, NULL)) /* ignore errors */
585 *value_is_writable = TRUE;
586
587 val = gconf_source_query_value (source, key, locales,
588 schema_name_retloc, &error);
589
590 }
591 else if (schema_name_retloc != NULL)
592 {
593 GConfMetaInfo *mi;
594
595 mi = gconf_source_query_metainfo (source, key, &error);
596
597 if (mi)
598 {
599 *schema_name_retloc = mi->schema;
600 mi->schema = NULL;
601 gconf_meta_info_free (mi);
602 }
603 }
604
605 if (error != NULL)
606 {
607 if (err)
608 *err = error;
609 else
610 g_error_free (error);
611
612 error = NULL;
613
614 if (val)
615 gconf_value_free (val);
616
617 g_free (schema_name);
618
619 return NULL;
620 }
621
622 /* schema_name_retloc == NULL means we aren't still looking for schema name,
623 * tmp->next == NULL means we aren't going to get a schema name
624 */
625 if (val != NULL && (schema_name_retloc == NULL || schema_name != NULL || tmp->next == NULL))
626 {
627 if (schema_namep)
628 *schema_namep = schema_name;
629 else
630 g_free (schema_name);
631
632 return val;
633 }
634 else
635 {
636 ; /* Keep looking for either val or schema name */
637 }
638
639 tmp = g_list_next (tmp);
640 }
641
642 g_return_val_if_fail (error == NULL, NULL);
643 g_return_val_if_fail (val == NULL, NULL);
644
645 /* If we got here, there was no value; we try to look up the
646 * schema for this key if we have one, and use the default
647 * value.
648 */
649
650 if (schema_name != NULL)
651 {
652 /* Note that if the value isn't found, then it's always the
653 * default value - even if there is no default value, NULL is
654 * the default. This makes things more sane (I think) because
655 * is_default basically means "was set by user" - however we
656 * also want to say that if use_schema_default is FALSE then
657 * value_is_default will be FALSE so we put this inside the
658 * schema_name != NULL conditional
659 */
660 if (value_is_default)
661 *value_is_default = TRUE;
662
663 if (use_schema_default)
664 {
665 val = gconf_sources_query_value (sources, schema_name, locales,
666 FALSE, NULL, NULL, NULL, &error);
667 }
668
669 if (error != NULL)
670 {
671 if (err)
672 *err = error;
673 else
674 g_error_free(error);
675
676 g_free(schema_name);
677 return NULL;
678 }
679 else if (val != NULL &&
680 val->type != GCONF_VALUE_SCHEMA)
681 {
682 gconf_set_error (err, GCONF_ERROR_FAILED,
683 _("Schema `%s' specified for `%s' stores a non-schema value"), schema_name, key);
684
685 if (schema_namep)
686 *schema_namep = schema_name;
687 else
688 g_free (schema_name);
689
690 return NULL;
691 }
692 else if (val != NULL)
693 {
694 GConfValue* retval;
695
696 retval = gconf_schema_steal_default_value (gconf_value_get_schema (val));
697
698 gconf_value_free (val);
699
700 if (schema_namep)
701 *schema_namep = schema_name;
702 else
703 g_free (schema_name);
704
705 return retval;
706 }
707 else
708 {
709 if (schema_namep)
710 *schema_namep = schema_name;
711 else
712 g_free (schema_name);
713
714 return NULL;
715 }
716 }
717
718 return NULL;
719 }
720
721 void
gconf_sources_set_value(GConfSources * sources,const gchar * key,const GConfValue * value,GConfSources ** modified_sources,GError ** err)722 gconf_sources_set_value (GConfSources* sources,
723 const gchar* key,
724 const GConfValue* value,
725 GConfSources **modified_sources,
726 GError** err)
727 {
728 GList* tmp;
729
730 g_return_if_fail(sources != NULL);
731 g_return_if_fail(key != NULL);
732 g_return_if_fail((err == NULL) || (*err == NULL));
733
734 if (modified_sources)
735 *modified_sources = NULL;
736
737 if (!gconf_key_check(key, err))
738 return;
739
740 g_assert(*key != '\0');
741
742 if (key[1] == '\0')
743 {
744 gconf_set_error(err, GCONF_ERROR_IS_DIR,
745 _("The '/' name can only be a directory, not a key"));
746 return;
747 }
748
749 tmp = sources->sources;
750
751 while (tmp != NULL)
752 {
753 GConfSource* src = tmp->data;
754
755 gconf_log (GCL_DEBUG, "Setting %s in %s",
756 key, src->address);
757
758 /* gconf_source_set_value return value is whether source
759 * was writable at key, not whether err was set.
760 */
761 if (gconf_source_set_value (src, key, value, err))
762 {
763 /* source was writable, err may be set */
764 gconf_log (GCL_DEBUG, "%s was writable in %s", key, src->address);
765 if (modified_sources)
766 {
767 *modified_sources = gconf_sources_new_from_source (src);
768 }
769 return;
770 }
771 else
772 {
773 /* check whether the value is set; if it is, then
774 we return an error since setting an overridden value
775 would have no effect
776 */
777 GConfValue* val;
778
779 val = gconf_source_query_value(tmp->data, key, NULL, NULL, NULL);
780
781 if (val != NULL)
782 {
783 gconf_log (GCL_DEBUG, "%s was already set in %s", key, src->address);
784
785 gconf_value_free(val);
786 gconf_set_error(err, GCONF_ERROR_OVERRIDDEN,
787 _("Value for `%s' set in a read-only source at the front of your configuration path"), key);
788 return;
789 }
790 }
791
792 tmp = g_list_next(tmp);
793 }
794
795 /* If we arrived here, then there was nowhere to write a value */
796 g_set_error (err,
797 GCONF_ERROR,
798 GCONF_ERROR_NO_WRITABLE_DATABASE,
799 _("Unable to store a value at key '%s', as the configuration server has no writable databases. There are some common causes of this problem: 1) your configuration path file %s/path doesn't contain any databases or wasn't found 2) somehow we mistakenly created two gconfd processes 3) your operating system is misconfigured so NFS file locking doesn't work in your home directory or 4) your NFS client machine crashed and didn't properly notify the server on reboot that file locks should be dropped. If you have two gconfd processes (or had two at the time the second was launched), logging out, killing all copies of gconfd, and logging back in may help. If you have stale locks, remove ~/.gconf*/*lock. Perhaps the problem is that you attempted to use GConf from two machines at once, and ORBit still has its default configuration that prevents remote CORBA connections - put \"ORBIIOPIPv4=1\" in /etc/orbitrc. As always, check the user.* syslog for details on problems gconfd encountered. There can only be one gconfd per home directory, and it must own a lockfile in ~/.gconfd and also lockfiles in individual storage locations such as ~/.gconf"),
800 key, GCONF_CONFDIR);
801 }
802
803 void
gconf_sources_unset_value(GConfSources * sources,const gchar * key,const gchar * locale,GConfSources ** modified_sources,GError ** err)804 gconf_sources_unset_value (GConfSources* sources,
805 const gchar* key,
806 const gchar* locale,
807 GConfSources **modified_sources,
808 GError** err)
809 {
810 /* We unset in every layer we can write to... */
811 GList* tmp;
812 GError* error = NULL;
813
814 tmp = sources->sources;
815
816 while (tmp != NULL)
817 {
818 GConfSource* src = tmp->data;
819
820 if (gconf_source_unset_value(src, key, locale, &error))
821 {
822 /* it was writable */
823
824 /* On error, set error and bail */
825 if (error != NULL)
826 {
827 if (err)
828 {
829 g_return_if_fail(*err == NULL);
830 *err = error;
831 return;
832 }
833 else
834 {
835 g_error_free(error);
836 return;
837 }
838 }
839
840 if (modified_sources)
841 {
842 if (*modified_sources == NULL)
843 {
844 *modified_sources = gconf_sources_new_from_source (src);
845 }
846 else
847 {
848 (*modified_sources)->sources =
849 g_list_prepend ((*modified_sources)->sources, src);
850 }
851 }
852 }
853
854 tmp = g_list_next(tmp);
855 }
856 }
857
858 static GSList *
prepend_unset_notify(GSList * notifies,GConfSources * modified_sources,char * key)859 prepend_unset_notify (GSList *notifies,
860 GConfSources *modified_sources,
861 char *key)
862 {
863 GConfUnsetNotify *notify;
864
865 g_assert (modified_sources != NULL);
866 g_assert (key != NULL);
867
868 notify = g_new0 (GConfUnsetNotify, 1);
869
870 notify->modified_sources = modified_sources;
871 notify->key = key;
872
873 return g_slist_append (notifies, notify);
874 }
875
876 static void
recursive_unset_helper(GConfSources * sources,const char * key,const char * locale,GConfUnsetFlags flags,GSList ** notifies,GError ** first_error)877 recursive_unset_helper (GConfSources *sources,
878 const char *key,
879 const char *locale,
880 GConfUnsetFlags flags,
881 GSList **notifies,
882 GError **first_error)
883 {
884 GError* err = NULL;
885 GSList* subdirs;
886 GSList* entries;
887 GSList* tmp;
888 const char *locales[2] = { NULL, NULL };
889 GConfSources* modified_sources;
890 GConfSources** modifiedp = NULL;
891
892 if (notifies)
893 {
894 modified_sources = NULL;
895 modifiedp = &modified_sources;
896 }
897
898 err = NULL;
899
900 subdirs = gconf_sources_all_dirs (sources, key, &err);
901
902 if (subdirs != NULL)
903 {
904 tmp = subdirs;
905
906 while (tmp != NULL)
907 {
908 char *s = tmp->data;
909 char *full = gconf_concat_dir_and_key (key, s);
910
911 recursive_unset_helper (sources, full, locale, flags,
912 notifies, first_error);
913
914 g_free (s);
915 g_free (full);
916
917 tmp = g_slist_next (tmp);
918 }
919
920 g_slist_free (subdirs);
921 }
922 else
923 {
924 if (err != NULL)
925 {
926 gconf_log (GCL_DEBUG, "Error listing subdirs of '%s': %s\n",
927 key, err->message);
928 if (*first_error)
929 g_error_free (err);
930 else
931 *first_error = err;
932 err = NULL;
933 }
934 }
935
936 locales[0] = locale;
937 entries = gconf_sources_all_entries (sources, key,
938 locale ? locales : NULL,
939 &err);
940
941 if (err != NULL)
942 {
943 gconf_log (GCL_DEBUG, "Failure listing entries in '%s': %s\n",
944 key, err->message);
945 if (*first_error)
946 g_error_free (err);
947 else
948 *first_error = err;
949 err = NULL;
950 }
951
952 if (entries != NULL)
953 {
954 tmp = entries;
955
956 while (tmp != NULL)
957 {
958 GConfEntry* entry = tmp->data;
959 char *full, *freeme;
960
961 full = freeme = gconf_concat_dir_and_key (key,
962 gconf_entry_get_key (entry));
963
964
965 gconf_sources_unset_value (sources, full, locale, modifiedp, &err);
966 if (notifies)
967 {
968 *notifies = prepend_unset_notify (*notifies, modified_sources, full);
969 modified_sources = NULL;
970 freeme = NULL;
971 }
972
973 if (err != NULL)
974 {
975 gconf_log (GCL_DEBUG, "Error unsetting '%s': %s\n",
976 full, err->message);
977
978 if (*first_error)
979 g_error_free (err);
980 else
981 *first_error = err;
982 err = NULL;
983 }
984
985 if (flags & GCONF_UNSET_INCLUDING_SCHEMA_NAMES)
986 {
987 gconf_sources_set_schema (sources,
988 full, NULL,
989 &err);
990 if (err != NULL)
991 {
992 gconf_log (GCL_DEBUG, "Error unsetting schema on '%s': %s\n",
993 full, err->message);
994
995 if (*first_error)
996 g_error_free (err);
997 else
998 *first_error = err;
999 err = NULL;
1000 }
1001 }
1002
1003 gconf_entry_free (entry);
1004 g_free (freeme);
1005
1006 tmp = g_slist_next (tmp);
1007 }
1008
1009 g_slist_free (entries);
1010 }
1011
1012 gconf_sources_unset_value (sources, key, locale, modifiedp, &err);
1013 if (notifies)
1014 {
1015 *notifies = prepend_unset_notify (*notifies,
1016 modified_sources,
1017 g_strdup (key));
1018 modified_sources = NULL;
1019 }
1020
1021 if (err != NULL)
1022 {
1023 gconf_log (GCL_DEBUG, "Error unsetting '%s': %s\n",
1024 key, err->message);
1025
1026 if (*first_error)
1027 g_error_free (err);
1028 else
1029 *first_error = err;
1030 err = NULL;
1031 }
1032 }
1033
1034 void
gconf_sources_recursive_unset(GConfSources * sources,const gchar * key,const gchar * locale,GConfUnsetFlags flags,GSList ** notifies,GError ** err)1035 gconf_sources_recursive_unset (GConfSources *sources,
1036 const gchar *key,
1037 const gchar *locale,
1038 GConfUnsetFlags flags,
1039 GSList **notifies,
1040 GError **err)
1041 {
1042 GError *first_error;
1043
1044 g_return_if_fail (sources != NULL);
1045 g_return_if_fail (key != NULL);
1046 g_return_if_fail (err == NULL || *err == NULL);
1047
1048 first_error = NULL;
1049 recursive_unset_helper (sources, key, locale, flags,
1050 notifies, &first_error);
1051
1052 if (first_error)
1053 {
1054 if (notifies != NULL && *notifies != NULL)
1055 {
1056 GSList *tmp;
1057
1058 tmp = *notifies;
1059 while (tmp != NULL)
1060 {
1061 GConfUnsetNotify *notify = tmp->data;
1062
1063 g_free (notify->key);
1064 g_free (notify);
1065
1066 tmp = tmp->next;
1067 }
1068
1069 g_slist_free (*notifies);
1070 *notifies = NULL;
1071 }
1072
1073 g_propagate_error (err, first_error);
1074 }
1075 }
1076
1077 gboolean
gconf_sources_dir_exists(GConfSources * sources,const gchar * dir,GError ** err)1078 gconf_sources_dir_exists (GConfSources* sources,
1079 const gchar* dir,
1080 GError** err)
1081 {
1082 GList *tmp;
1083
1084 if (!gconf_key_check(dir, err))
1085 return FALSE;
1086
1087 tmp = sources->sources;
1088
1089 while (tmp != NULL)
1090 {
1091 GConfSource* src = tmp->data;
1092
1093 if (gconf_source_dir_exists (src, dir, err))
1094 return TRUE;
1095
1096 tmp = g_list_next(tmp);
1097 }
1098
1099 return FALSE;
1100 }
1101
1102 void
gconf_sources_remove_dir(GConfSources * sources,const gchar * dir,GError ** err)1103 gconf_sources_remove_dir (GConfSources* sources,
1104 const gchar* dir,
1105 GError** err)
1106 {
1107 /* We remove in every layer we can write to... */
1108 GList* tmp;
1109
1110 if (!gconf_key_check(dir, err))
1111 return;
1112
1113 tmp = sources->sources;
1114
1115 while (tmp != NULL)
1116 {
1117 GConfSource* src = tmp->data;
1118 GError* error = NULL;
1119
1120 gconf_source_remove_dir(src, dir, &error);
1121
1122 /* On error, set error and bail */
1123 if (error != NULL)
1124 {
1125 if (err)
1126 {
1127 g_return_if_fail(*err == NULL);
1128 *err = error;
1129 return;
1130 }
1131 else
1132 {
1133 g_error_free(error);
1134 return;
1135 }
1136 }
1137
1138 tmp = g_list_next(tmp);
1139 }
1140 }
1141
1142 void
gconf_sources_set_schema(GConfSources * sources,const gchar * key,const gchar * schema_key,GError ** err)1143 gconf_sources_set_schema (GConfSources *sources,
1144 const gchar *key,
1145 const gchar *schema_key,
1146 GError **err)
1147 {
1148 GList* tmp;
1149
1150 if (!gconf_key_check (key, err))
1151 return;
1152
1153 if (schema_key && !gconf_key_check (schema_key, err))
1154 return;
1155
1156 tmp = sources->sources;
1157
1158 while (tmp != NULL)
1159 {
1160 GConfSource* src = tmp->data;
1161
1162 /* may set error, we just leave its setting */
1163 /* returns TRUE if the source was writable */
1164 if (gconf_source_set_schema (src, key, schema_key, err))
1165 return;
1166
1167 tmp = g_list_next(tmp);
1168 }
1169 }
1170
1171 /* God, this is depressingly inefficient. Maybe there's a nicer way to
1172 implement it... */
1173 /* Then we have to ship it all to the app via CORBA... */
1174 /* Anyway, we use a hash to be sure we have a single value for
1175 each key in the directory, and we always take that value from
1176 the first source that had one set. When we're done we flatten
1177 the hash.
1178 */
1179 static void
hash_listify_func(gpointer key,gpointer value,gpointer user_data)1180 hash_listify_func(gpointer key, gpointer value, gpointer user_data)
1181 {
1182 GSList** list_p = user_data;
1183
1184 *list_p = g_slist_prepend(*list_p, value);
1185 }
1186
1187 static void
hash_destroy_entries_func(gpointer key,gpointer value,gpointer user_data)1188 hash_destroy_entries_func(gpointer key, gpointer value, gpointer user_data)
1189 {
1190 GConfEntry* entry;
1191
1192 entry = value;
1193
1194 gconf_entry_free(entry);
1195 }
1196
1197 static void
hash_destroy_pointers_func(gpointer key,gpointer value,gpointer user_data)1198 hash_destroy_pointers_func(gpointer key, gpointer value, gpointer user_data)
1199 {
1200 g_free(value);
1201 }
1202
1203 struct DefaultsLookupData {
1204 GConfSources* sources;
1205 const gchar** locales;
1206 };
1207
1208 static void
hash_lookup_defaults_func(gpointer key,gpointer value,gpointer user_data)1209 hash_lookup_defaults_func(gpointer key, gpointer value, gpointer user_data)
1210 {
1211 GConfEntry *entry = value;
1212 struct DefaultsLookupData* dld = user_data;
1213 GConfSources *sources = dld->sources;
1214 const gchar** locales = dld->locales;
1215
1216 if (gconf_entry_get_value(entry) == NULL)
1217 {
1218 if (gconf_entry_get_schema_name(entry) != NULL)
1219 {
1220 GConfValue *val;
1221
1222
1223 val = gconf_sources_query_value(sources,
1224 gconf_entry_get_schema_name(entry),
1225 locales,
1226 TRUE,
1227 NULL,
1228 NULL,
1229 NULL,
1230 NULL);
1231
1232 if (val != NULL &&
1233 val->type == GCONF_VALUE_SCHEMA)
1234 {
1235 GConfValue* defval;
1236
1237 defval = gconf_schema_steal_default_value (gconf_value_get_schema(val));
1238
1239 gconf_entry_set_value_nocopy (entry, defval);
1240 gconf_entry_set_is_default (entry, TRUE);
1241 }
1242
1243 if (val)
1244 gconf_value_free(val);
1245 }
1246 }
1247 }
1248
1249
1250 static gboolean
key_is_writable(GConfSources * sources,GConfSource * value_in_src,const gchar * key,GError ** err)1251 key_is_writable (GConfSources *sources,
1252 GConfSource *value_in_src,
1253 const gchar *key,
1254 GError **err)
1255 {
1256 GList *tmp;
1257
1258 tmp = sources->sources;
1259
1260 while (tmp != NULL)
1261 {
1262 GConfSource* src;
1263
1264 src = tmp->data;
1265
1266 if (source_is_writable (src, key, NULL))
1267 return TRUE;
1268
1269 if (src == value_in_src)
1270 return FALSE; /* didn't find a writable source before value-containing
1271 source.
1272 */
1273
1274 tmp = g_list_next (tmp);
1275 }
1276
1277 /* This shouldn't be reached actually */
1278 return FALSE;
1279 }
1280
1281 GSList*
gconf_sources_all_entries(GConfSources * sources,const gchar * dir,const gchar ** locales,GError ** err)1282 gconf_sources_all_entries (GConfSources* sources,
1283 const gchar* dir,
1284 const gchar** locales,
1285 GError** err)
1286 {
1287 GList* tmp;
1288 GHashTable* hash;
1289 GSList* flattened;
1290 gboolean first_pass = TRUE; /* as an optimization, don't bother
1291 doing hash lookups on first source
1292 */
1293 struct DefaultsLookupData dld = { NULL, NULL };
1294
1295 dld.sources = sources;
1296 dld.locales = locales;
1297
1298 /* Empty GConfSources, skip it */
1299 if (sources->sources == NULL)
1300 return NULL;
1301
1302 hash = g_hash_table_new(g_str_hash, g_str_equal);
1303
1304 tmp = sources->sources;
1305
1306 while (tmp != NULL)
1307 {
1308 GConfSource* src;
1309 GSList* pairs;
1310 GSList* iter;
1311 GError* error = NULL;
1312
1313 src = tmp->data;
1314 pairs = gconf_source_all_entries(src, dir, locales, &error);
1315 iter = pairs;
1316
1317 /* On error, set error and bail */
1318 if (error != NULL)
1319 {
1320 g_hash_table_foreach(hash, hash_destroy_entries_func, NULL);
1321
1322 g_hash_table_destroy(hash);
1323
1324 if (err)
1325 {
1326 g_return_val_if_fail(*err == NULL, NULL);
1327 *err = error;
1328 return NULL;
1329 }
1330 else
1331 {
1332 g_error_free(error);
1333 return NULL;
1334 }
1335 }
1336
1337 /* Iterate over the list of entries, stuffing them in the hash
1338 and setting their writability flag if they're new
1339 */
1340
1341 while (iter != NULL)
1342 {
1343 GConfEntry* pair = iter->data;
1344 GConfEntry* previous;
1345 gchar *full;
1346
1347 if (first_pass)
1348 previous = NULL; /* Can't possibly be there. */
1349 else
1350 previous = g_hash_table_lookup(hash, pair->key);
1351
1352 if (previous != NULL)
1353 {
1354 if (gconf_entry_get_value (previous) != NULL)
1355 /* Discard this latest one */
1356 ;
1357 else
1358 {
1359 /* Save the new value, previously we had an entry but no value */
1360 gconf_entry_set_value_nocopy (previous,
1361 gconf_entry_steal_value(pair));
1362
1363 /* As an efficiency hack, remember that
1364 * entry->key is relative not absolute on the
1365 * gconfd side
1366 */
1367 full = gconf_concat_dir_and_key (dir, previous->key);
1368
1369 gconf_entry_set_is_writable (previous,
1370 key_is_writable (sources,
1371 src,
1372 full,
1373 NULL));
1374
1375 g_free (full);
1376 }
1377
1378 if (gconf_entry_get_schema_name (previous) != NULL)
1379 /* Discard this latest one */
1380 ;
1381 else
1382 {
1383 /* Save the new schema name, previously we had an entry but no schema name*/
1384 if (gconf_entry_get_schema_name (pair) != NULL)
1385 {
1386 gconf_entry_set_schema_name (previous,
1387 gconf_entry_get_schema_name (pair));
1388 }
1389 }
1390
1391 gconf_entry_free(pair);
1392 }
1393 else
1394 {
1395 /* Save */
1396 g_hash_table_insert(hash, pair->key, pair);
1397
1398 /* As an efficiency hack, remember that
1399 * entry->key is relative not absolute on the
1400 * gconfd side
1401 */
1402 full = gconf_concat_dir_and_key (dir, pair->key);
1403
1404 gconf_entry_set_is_writable (pair,
1405 key_is_writable (sources,
1406 src,
1407 full,
1408 NULL));
1409
1410 g_free (full);
1411 }
1412
1413 iter = g_slist_next(iter);
1414 }
1415
1416 /* All pairs are either stored or destroyed. */
1417 g_slist_free(pairs);
1418
1419 first_pass = FALSE;
1420
1421 tmp = g_list_next(tmp);
1422 }
1423
1424 flattened = NULL;
1425
1426 g_hash_table_foreach(hash, hash_lookup_defaults_func, &dld);
1427
1428 g_hash_table_foreach(hash, hash_listify_func, &flattened);
1429
1430 g_hash_table_destroy(hash);
1431
1432 return flattened;
1433 }
1434
1435 GSList*
gconf_sources_all_dirs(GConfSources * sources,const gchar * dir,GError ** err)1436 gconf_sources_all_dirs (GConfSources* sources,
1437 const gchar* dir,
1438 GError** err)
1439 {
1440 GList* tmp = NULL;
1441 GHashTable* hash = NULL;
1442 GSList* flattened = NULL;
1443 gboolean first_pass = TRUE; /* as an optimization, don't bother
1444 doing hash lookups on first source
1445 */
1446
1447 g_return_val_if_fail(sources != NULL, NULL);
1448 g_return_val_if_fail(dir != NULL, NULL);
1449
1450 /* As another optimization, skip the whole
1451 hash thing if there's only zero or one sources
1452 */
1453 if (sources->sources == NULL)
1454 return NULL;
1455
1456 if (sources->sources->next == NULL)
1457 {
1458 return gconf_source_all_dirs (sources->sources->data, dir, err);
1459 }
1460
1461 /* 2 or more sources */
1462 g_assert(g_list_length(sources->sources) > 1);
1463
1464 hash = g_hash_table_new(g_str_hash, g_str_equal);
1465
1466 tmp = sources->sources;
1467
1468 while (tmp != NULL)
1469 {
1470 GConfSource* src;
1471 GSList* subdirs;
1472 GSList* iter;
1473 GError* error = NULL;
1474
1475 src = tmp->data;
1476 subdirs = gconf_source_all_dirs(src, dir, &error);
1477 iter = subdirs;
1478
1479 /* On error, set error and bail */
1480 if (error != NULL)
1481 {
1482 g_hash_table_foreach (hash, hash_destroy_pointers_func, NULL);
1483
1484 g_hash_table_destroy (hash);
1485
1486 if (err)
1487 {
1488 g_return_val_if_fail(*err == NULL, NULL);
1489 *err = error;
1490 return NULL;
1491 }
1492 else
1493 {
1494 g_error_free(error);
1495 return NULL;
1496 }
1497 }
1498
1499 while (iter != NULL)
1500 {
1501 gchar* subdir = iter->data;
1502 gchar* previous;
1503
1504 if (first_pass)
1505 previous = NULL; /* Can't possibly be there. */
1506 else
1507 previous = g_hash_table_lookup(hash, subdir);
1508
1509 if (previous != NULL)
1510 {
1511 /* Discard */
1512 g_free(subdir);
1513 }
1514 else
1515 {
1516 /* Save */
1517 g_hash_table_insert(hash, subdir, subdir);
1518 }
1519
1520 iter = g_slist_next(iter);
1521 }
1522
1523 /* All pairs are either stored or destroyed. */
1524 g_slist_free(subdirs);
1525
1526 first_pass = FALSE;
1527
1528 tmp = g_list_next(tmp);
1529 }
1530
1531 flattened = NULL;
1532
1533 g_hash_table_foreach(hash, hash_listify_func, &flattened);
1534
1535 g_hash_table_destroy(hash);
1536
1537 return flattened;
1538 }
1539
1540 gboolean
gconf_sources_sync_all(GConfSources * sources,GError ** err)1541 gconf_sources_sync_all (GConfSources* sources, GError** err)
1542 {
1543 GList* tmp;
1544 gboolean failed = FALSE;
1545 GError* all_errors = NULL;
1546
1547 tmp = sources->sources;
1548
1549 while (tmp != NULL)
1550 {
1551 GConfSource* src = tmp->data;
1552 GError* error = NULL;
1553
1554 if (!gconf_source_sync_all(src, &error))
1555 {
1556 failed = TRUE;
1557 g_assert(error != NULL);
1558 }
1559
1560 /* On error, set error and bail */
1561 if (error != NULL)
1562 {
1563 if (err)
1564 all_errors = gconf_compose_errors(all_errors, error);
1565
1566 g_error_free(error);
1567 }
1568
1569 tmp = g_list_next(tmp);
1570 }
1571
1572 if (err)
1573 {
1574 g_return_val_if_fail(*err == NULL, !failed);
1575 *err = all_errors;
1576 }
1577
1578 return !failed;
1579 }
1580
1581 GConfMetaInfo*
gconf_sources_query_metainfo(GConfSources * sources,const gchar * key,GError ** err)1582 gconf_sources_query_metainfo (GConfSources* sources,
1583 const gchar* key,
1584 GError** err)
1585 {
1586 GList* tmp;
1587 GConfMetaInfo* mi = NULL;
1588
1589 tmp = sources->sources;
1590
1591 while (tmp != NULL)
1592 {
1593 GConfSource* src = tmp->data;
1594 GError* error = NULL;
1595 GConfMetaInfo* this_mi;
1596
1597 this_mi = gconf_source_query_metainfo(src, key, &error);
1598
1599 /* On error, just keep going, log the error maybe. */
1600 if (error != NULL)
1601 {
1602 g_assert(this_mi == NULL);
1603 gconf_log(GCL_ERR, _("Error finding metainfo: %s"), error->message);
1604 g_error_free(error);
1605 error = NULL;
1606 }
1607
1608 if (this_mi != NULL)
1609 {
1610 if (mi == NULL)
1611 mi = this_mi;
1612 else
1613 {
1614 /* Fill in any missing fields of "mi" found in "this_mi",
1615 and pick the most recent mod time */
1616 if (gconf_meta_info_get_schema(mi) == NULL &&
1617 gconf_meta_info_get_schema(this_mi) != NULL)
1618 {
1619 gconf_meta_info_set_schema(mi,
1620 gconf_meta_info_get_schema(this_mi));
1621 }
1622
1623 if (gconf_meta_info_get_mod_user(mi) == NULL &&
1624 gconf_meta_info_get_mod_user(this_mi) != NULL)
1625 {
1626 gconf_meta_info_set_mod_user(mi,
1627 gconf_meta_info_get_mod_user(this_mi));
1628 }
1629
1630 if (gconf_meta_info_mod_time(mi) < gconf_meta_info_mod_time(this_mi))
1631 {
1632 gconf_meta_info_set_mod_time(mi,
1633 gconf_meta_info_mod_time(this_mi));
1634 }
1635
1636 gconf_meta_info_free(this_mi);
1637 }
1638 }
1639
1640 tmp = g_list_next(tmp);
1641 }
1642
1643 return mi;
1644 }
1645
1646 GConfValue*
gconf_sources_query_default_value(GConfSources * sources,const gchar * key,const gchar ** locales,gboolean * is_writable,GError ** err)1647 gconf_sources_query_default_value(GConfSources* sources,
1648 const gchar* key,
1649 const gchar** locales,
1650 gboolean* is_writable,
1651 GError** err)
1652 {
1653 GError* error = NULL;
1654 GConfValue* val;
1655 GConfMetaInfo* mi;
1656
1657 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1658
1659 if (is_writable)
1660 *is_writable = key_is_writable (sources, NULL, key, NULL);
1661
1662 mi = gconf_sources_query_metainfo(sources, key,
1663 &error);
1664 if (mi == NULL)
1665 {
1666 if (error != NULL)
1667 {
1668 if (err)
1669 *err = error;
1670 else
1671 {
1672 gconf_log(GCL_ERR, _("Error getting metainfo: %s"), error->message);
1673 g_error_free(error);
1674 }
1675 }
1676 return NULL;
1677 }
1678
1679 if (gconf_meta_info_get_schema(mi) == NULL)
1680 {
1681 gconf_meta_info_free(mi);
1682 return NULL;
1683 }
1684
1685 val = gconf_sources_query_value(sources,
1686 gconf_meta_info_get_schema(mi), locales,
1687 TRUE, NULL, NULL, NULL, &error);
1688
1689 if (val != NULL)
1690 {
1691 GConfSchema* schema;
1692
1693 if (val->type != GCONF_VALUE_SCHEMA)
1694 {
1695 gconf_log(GCL_WARNING,
1696 _("Key `%s' listed as schema for key `%s' actually stores type `%s'"),
1697 gconf_meta_info_get_schema(mi),
1698 key,
1699 gconf_value_type_to_string(val->type));
1700
1701 gconf_meta_info_free(mi);
1702 return NULL;
1703 }
1704
1705 gconf_meta_info_free(mi);
1706
1707 schema = gconf_value_steal_schema (val);
1708 gconf_value_free (val);
1709
1710 if (schema != NULL)
1711 {
1712 GConfValue* retval;
1713
1714 retval = gconf_schema_steal_default_value (schema);
1715
1716 gconf_schema_free (schema);
1717
1718 return retval;
1719 }
1720 return NULL;
1721 }
1722 else
1723 {
1724 if (error != NULL)
1725 {
1726 if (err)
1727 *err = error;
1728 else
1729 {
1730 gconf_log(GCL_ERR, _("Error getting value for `%s': %s"),
1731 gconf_meta_info_get_schema(mi),
1732 error->message);
1733 g_error_free(error);
1734 }
1735 }
1736
1737 gconf_meta_info_free(mi);
1738
1739 return NULL;
1740 }
1741 }
1742
1743 void
gconf_sources_set_notify_func(GConfSources * sources,GConfSourceNotifyFunc notify_func,gpointer user_data)1744 gconf_sources_set_notify_func (GConfSources *sources,
1745 GConfSourceNotifyFunc notify_func,
1746 gpointer user_data)
1747 {
1748 GList *tmp;
1749
1750 tmp = sources->sources;
1751 while (tmp != NULL)
1752 {
1753 gconf_source_set_notify_func (tmp->data, notify_func, user_data);
1754
1755 tmp = tmp->next;
1756 }
1757 }
1758
1759 void
gconf_sources_add_listener(GConfSources * sources,guint id,const gchar * namespace_section)1760 gconf_sources_add_listener (GConfSources *sources,
1761 guint id,
1762 const gchar *namespace_section)
1763 {
1764 GList *tmp;
1765
1766 tmp = sources->sources;
1767 while (tmp != NULL)
1768 {
1769 gconf_source_add_listener (tmp->data, id, namespace_section);
1770
1771 tmp = tmp->next;
1772 }
1773 }
1774
1775 void
gconf_sources_remove_listener(GConfSources * sources,guint id)1776 gconf_sources_remove_listener (GConfSources *sources,
1777 guint id)
1778 {
1779 GList *tmp;
1780
1781 tmp = sources->sources;
1782 while (tmp != NULL)
1783 {
1784 gconf_source_remove_listener (tmp->data, id);
1785
1786 tmp = tmp->next;
1787 }
1788 }
1789
1790 /* Non-allocating variant of gconf_address_resource()
1791 */
1792 static const char *
get_address_resource(const char * address)1793 get_address_resource (const char *address)
1794 {
1795 const char *start;
1796
1797 g_return_val_if_fail (address != NULL, NULL);
1798
1799 start = strchr (address, ':');
1800 if (start != NULL)
1801 {
1802 start = strchr (++start, ':');
1803
1804 if (start != NULL)
1805 start++;
1806 }
1807
1808 return start;
1809 }
1810
1811 /* Return TRUE if
1812 * 1. @sources contains @modified_src and
1813 * 2. @key is not set in any source above @modified_src.
1814 */
1815 gboolean
gconf_sources_is_affected(GConfSources * sources,GConfSource * modified_src,const char * key)1816 gconf_sources_is_affected (GConfSources *sources,
1817 GConfSource *modified_src,
1818 const char *key)
1819 {
1820 const char *modified_resource;
1821 GList *tmp;
1822
1823 modified_resource = get_address_resource (modified_src->address);
1824
1825 tmp = sources->sources;
1826 while (tmp != NULL)
1827 {
1828 GConfSource *source = tmp->data;
1829
1830 if (source->backend == modified_src->backend &&
1831 strcmp (modified_resource, get_address_resource (source->address)) == 0)
1832 break;
1833
1834 tmp = tmp->next;
1835 }
1836
1837 if (tmp == NULL)
1838 return FALSE;
1839
1840 tmp = tmp->prev;
1841 while (tmp != NULL)
1842 {
1843 GConfValue *val;
1844
1845 val = gconf_source_query_value (tmp->data, key, NULL, NULL, NULL);
1846 if (val != NULL)
1847 {
1848 gconf_value_free (val);
1849 return FALSE;
1850 }
1851
1852 tmp = tmp->prev;
1853 }
1854
1855 return TRUE;
1856 }
1857