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