source: trunk/third/GConf/gconf/gconf-sources.c @ 17087

Revision 17087, 34.8 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17086, which included commits to RCS files with non-trunk default branches.
Line 
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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21#include "gconf-backend.h"
22#include "gconf-sources.h"
23#include "gconf-internals.h"
24#include "gconf-schema.h"
25#include "gconf.h"
26#include <string.h>
27#include <sys/stat.h>
28#include <sys/types.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <stdio.h>
32#include <fcntl.h>
33#include <errno.h>
34#include <ctype.h>
35
36/*
37 *  Sources
38 */
39
40GConfSource*
41gconf_resolve_address(const gchar* address, GError** err)
42{
43  GConfBackend* backend;
44
45  backend = gconf_get_backend(address, err);
46
47  if (backend == NULL)
48    return NULL;
49  else
50    {
51      GConfSource* retval;
52
53      retval = gconf_backend_resolve_address(backend, address, err);
54
55      if (retval == NULL)
56        {
57          gconf_backend_unref(backend);
58          return NULL;
59        }
60      else
61        {
62          retval->backend = backend;
63          retval->address = g_strdup(address);
64         
65          /* Leave a ref on the backend, now held by the GConfSource */
66         
67          return retval;
68        }
69    }
70}
71
72void         
73gconf_source_free (GConfSource* source)
74{
75  GConfBackend* backend;
76 
77  g_return_if_fail(source != NULL);
78
79  backend = source->backend;
80 
81  (*source->backend->vtable->destroy_source)(source);
82 
83  /* Remove ref held by the source. */
84  gconf_backend_unref(backend);
85}
86
87#define SOURCE_READABLE(source, key, err)                  \
88     ( ((source)->flags & GCONF_SOURCE_ALL_READABLE) ||    \
89       ((source)->backend->vtable->readable != NULL &&     \
90        (*(source)->backend->vtable->readable)((source), (key), (err))) )
91
92static gboolean
93source_is_writable(GConfSource* source, const gchar* key, GError** err)
94{
95  if ((source->flags & GCONF_SOURCE_NEVER_WRITEABLE) != 0)
96    return FALSE;
97  else if ((source->flags & GCONF_SOURCE_ALL_WRITEABLE) != 0)
98    return TRUE;
99  else if (source->backend->vtable->writable != NULL &&
100           (*source->backend->vtable->writable)(source, key, err))
101    return TRUE;
102  else
103    return FALSE;
104}
105
106static GConfValue*
107gconf_source_query_value      (GConfSource* source,
108                               const gchar* key,
109                               const gchar** locales,
110                               gchar** schema_name,
111                               GError** err)
112{
113  g_return_val_if_fail(source != NULL, NULL);
114  g_return_val_if_fail(key != NULL, NULL);
115  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
116 
117  /* note that key validity is unchecked */
118
119  if ( SOURCE_READABLE(source, key, err) )
120    {
121      g_return_val_if_fail(err == NULL || *err == NULL, NULL);
122      return (*source->backend->vtable->query_value)(source, key, locales, schema_name, err);
123    }
124  else
125    return NULL;
126}
127
128static GConfMetaInfo*
129gconf_source_query_metainfo      (GConfSource* source,
130                                  const gchar* key,
131                                  GError** err)
132{
133  g_return_val_if_fail(source != NULL, NULL);
134  g_return_val_if_fail(key != NULL, NULL);
135  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
136 
137  /* note that key validity is unchecked */
138
139  if ( SOURCE_READABLE(source, key, err) )
140    {
141      g_return_val_if_fail(err == NULL || *err == NULL, NULL);
142      return (*source->backend->vtable->query_metainfo)(source, key, err);
143    }
144  else
145    return NULL;
146}
147
148
149/* return value indicates whether the key was writable */
150static gboolean
151gconf_source_set_value        (GConfSource* source,
152                               const gchar* key,
153                               GConfValue* value,
154                               GError** err)
155{
156  g_return_val_if_fail(source != NULL, FALSE);
157  g_return_val_if_fail(value != NULL, FALSE);
158  g_return_val_if_fail(key != NULL, FALSE);
159  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
160 
161  /* don't check key validity */
162
163  if ( source_is_writable(source, key, err) )
164    {
165      g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
166      (*source->backend->vtable->set_value)(source, key, value, err);
167      return TRUE;
168    }
169  else
170    return FALSE;
171}
172
173static gboolean
174gconf_source_unset_value      (GConfSource* source,
175                               const gchar* key,
176                               const gchar* locale,
177                               GError** err)
178{
179  g_return_val_if_fail(source != NULL, FALSE);
180  g_return_val_if_fail(key != NULL, FALSE);
181  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
182 
183  if ( source_is_writable(source, key, err) )
184    {
185      g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
186
187      (*source->backend->vtable->unset_value)(source, key, locale, err);
188      return TRUE;
189    }
190  else
191    return FALSE;
192}
193
194static GSList*     
195gconf_source_all_entries         (GConfSource* source,
196                                  const gchar* dir,
197                                  const gchar** locales,
198                                  GError** err)
199{
200  g_return_val_if_fail(source != NULL, NULL);
201  g_return_val_if_fail(dir != NULL, NULL);
202  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
203 
204  if ( SOURCE_READABLE(source, dir, err) )
205    {
206      g_return_val_if_fail(err == NULL || *err == NULL, NULL);
207      return (*source->backend->vtable->all_entries)(source, dir, locales, err);
208    }
209  else
210    return NULL;
211}
212
213static GSList*     
214gconf_source_all_dirs          (GConfSource* source,
215                                const gchar* dir,
216                                GError** err)
217{
218  g_return_val_if_fail(source != NULL, NULL);
219  g_return_val_if_fail(dir != NULL, NULL); 
220  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
221 
222  if ( SOURCE_READABLE(source, dir, err) )
223    {
224      g_return_val_if_fail(err == NULL || *err == NULL, NULL);
225      return (*source->backend->vtable->all_subdirs)(source, dir, err);
226    }
227  else
228    return NULL;
229}
230
231static gboolean
232gconf_source_dir_exists        (GConfSource* source,
233                                const gchar* dir,
234                                GError** err)
235{
236  g_return_val_if_fail(source != NULL, FALSE);
237  g_return_val_if_fail(dir != NULL, FALSE);
238  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
239 
240  if ( SOURCE_READABLE(source, dir, err) )
241    {
242      g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
243      return (*source->backend->vtable->dir_exists)(source, dir, err);
244    }
245  else
246    return FALSE;
247}
248
249static void         
250gconf_source_remove_dir        (GConfSource* source,
251                                const gchar* dir,
252                                GError** err)
253{
254  g_return_if_fail(source != NULL);
255  g_return_if_fail(dir != NULL);
256  g_return_if_fail(err == NULL || *err == NULL);
257 
258  if ( source_is_writable(source, dir, err) )
259    {
260      g_return_if_fail(err == NULL || *err == NULL);
261      (*source->backend->vtable->remove_dir)(source, dir, err);
262    }
263}
264
265static gboolean   
266gconf_source_set_schema        (GConfSource* source,
267                                const gchar* key,
268                                const gchar* schema_key,
269                                GError** err)
270{
271  g_return_val_if_fail(source != NULL, FALSE);
272  g_return_val_if_fail(key != NULL, FALSE);
273  g_return_val_if_fail(schema_key != NULL, FALSE);
274  g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
275 
276  if ( source_is_writable(source, key, err) )
277    {
278      g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
279      (*source->backend->vtable->set_schema)(source, key, schema_key, err);
280      return TRUE;
281    }
282  else
283    return FALSE;
284}
285
286static gboolean
287gconf_source_sync_all         (GConfSource* source, GError** err)
288{
289  return (*source->backend->vtable->sync_all)(source, err);
290}
291
292/*
293 *   Source stacks
294 */
295
296GConfSources*
297gconf_sources_new_from_addresses(const gchar** addresses, GError** err)
298{
299  GConfSources* sources;
300
301  g_return_val_if_fail( (err == NULL) || (*err == NULL), NULL);
302 
303  sources = g_new0(GConfSources, 1);
304
305  while (*addresses != NULL)
306    {
307      GConfSource* source;
308      GError* error = NULL;
309     
310      source = gconf_resolve_address(*addresses, &error);
311
312      if (source != NULL)
313        {
314          sources->sources = g_list_prepend(sources->sources, source);
315          g_return_val_if_fail(error == NULL, NULL);
316        }
317      else
318        {
319          g_assert(error != NULL);
320          gconf_log(GCL_WARNING, _("Failed to load source `%s': %s"),
321                    *addresses, error->message);
322         
323          g_error_free(error);
324        }
325         
326      ++addresses;
327    }
328
329  sources->sources = g_list_reverse(sources->sources);
330 
331  return sources;
332}
333
334GConfSources*
335gconf_sources_new_from_source       (GConfSource* source)
336{
337  GConfSources* sources;
338 
339  sources = g_new0(GConfSources, 1);
340
341  sources->sources = g_list_append(NULL, source);
342
343  return sources;
344}
345
346void
347gconf_sources_free(GConfSources* sources)
348{
349  GList* tmp;
350
351  tmp = sources->sources;
352
353  while (tmp != NULL)
354    {
355      gconf_source_free(tmp->data);
356     
357      tmp = g_list_next(tmp);
358    }
359
360  g_list_free(sources->sources);
361
362  g_free(sources);
363}
364
365void
366gconf_sources_clear_cache        (GConfSources  *sources)
367{
368  GList* tmp;
369
370  tmp = sources->sources;
371
372  while (tmp != NULL)
373    {
374      GConfSource* source = tmp->data;
375
376      if (source->backend->vtable->clear_cache)
377        (*source->backend->vtable->clear_cache)(source);
378     
379      tmp = g_list_next(tmp);
380    }
381}
382
383GConfValue*   
384gconf_sources_query_value (GConfSources* sources,
385                           const gchar* key,
386                           const gchar** locales,
387                           gboolean use_schema_default,
388                           gboolean* value_is_default,
389                           gboolean* value_is_writable,
390                           gchar   **schema_namep,
391                           GError** err)
392{
393  GList* tmp;
394  gchar* schema_name;
395  GError* error;
396  GConfValue* val;
397 
398  g_return_val_if_fail (sources != NULL, NULL);
399  g_return_val_if_fail (key != NULL, NULL);
400  g_return_val_if_fail ((err == NULL) || (*err == NULL), NULL);
401
402  /* A value is writable if it is unset and a writable source exists,
403   * or if it's set and the setting is within or after a writable source.
404   * So basically if we see a writable source before we get the value,
405   * or get the value from a writable source, the value is writable.
406   */
407 
408  if (!gconf_key_check(key, err))
409    return NULL;
410
411  if (value_is_default)
412    *value_is_default = FALSE;
413
414  if (value_is_writable)
415    *value_is_writable = FALSE;
416
417  if (schema_namep)
418    *schema_namep = NULL;
419
420  val = NULL;
421  schema_name = NULL;
422  error = NULL;
423 
424  tmp = sources->sources;
425
426  while (tmp != NULL)
427    {
428      GConfSource* source;     
429      gchar** schema_name_retloc;
430
431      schema_name_retloc = &schema_name;
432      if (schema_name != NULL ||                          /* already have the schema name */
433          (schema_namep == NULL && !use_schema_default))  /* don't need to get the schema name */
434        schema_name_retloc = NULL;
435     
436      source = tmp->data;
437
438      if (val == NULL)
439        {
440          /* A key is writable if the source containing its value or
441           * an earlier source is writable
442           */         
443          if (value_is_writable &&
444              source_is_writable (source, key, NULL)) /* ignore errors */
445            *value_is_writable = TRUE;
446         
447          val = gconf_source_query_value (source, key, locales,
448                                          schema_name_retloc, &error);
449
450        }
451      else if (schema_name_retloc != NULL)
452        {
453          GConfMetaInfo *mi;
454         
455          mi = gconf_source_query_metainfo (source, key, &error);
456         
457          if (mi)
458            {
459              *schema_name_retloc = mi->schema;
460              mi->schema = NULL;
461              gconf_meta_info_free (mi);
462            }
463        }
464         
465      if (error != NULL)
466        {
467          if (err)
468            *err = error;
469          else
470            g_error_free (error);
471
472          error = NULL;
473
474          if (val)
475            gconf_value_free (val);
476
477          if (schema_name)
478            g_free (schema_name);
479         
480          return NULL;
481        }
482
483      /* schema_name_retloc == NULL means we aren't still looking for schema name,
484       * tmp->next == NULL means we aren't going to get a schema name
485       */
486      if (val != NULL && (schema_name_retloc == NULL || schema_name != NULL || tmp->next == NULL))
487        {
488          if (schema_namep)
489            *schema_namep = schema_name;
490          else
491            g_free (schema_name);
492         
493          return val;
494        }
495      else
496        {
497          ; /* Keep looking for either val or schema name */
498        }
499     
500      tmp = g_list_next (tmp);
501    }
502
503  g_return_val_if_fail (error == NULL, NULL);
504  g_return_val_if_fail (val == NULL, NULL);
505 
506  /* If we got here, there was no value; we try to look up the
507   * schema for this key if we have one, and use the default
508   * value.
509   */
510 
511  if (schema_name != NULL)
512    {
513      /* Note that if the value isn't found, then it's always the
514       * default value - even if there is no default value, NULL is
515       * the default.  This makes things more sane (I think) because
516       * is_default basically means "was set by user" - however we
517       * also want to say that if use_schema_default is FALSE then
518       * value_is_default will be FALSE so we put this inside the
519       * schema_name != NULL conditional
520      */
521      if (value_is_default)
522        *value_is_default = TRUE;
523
524      if (use_schema_default)
525        {
526          val = gconf_sources_query_value (sources, schema_name, locales,
527                                           FALSE, NULL, NULL, NULL, &error);
528        }
529     
530      if (error != NULL)
531        {
532          if (err)
533            *err = error;
534          else
535            g_error_free(error);
536
537          g_free(schema_name);
538          return NULL;
539        }
540      else if (val != NULL &&
541               val->type != GCONF_VALUE_SCHEMA)
542        {
543          gconf_set_error (err, GCONF_ERROR_FAILED,
544                           _("Schema `%s' specified for `%s' stores a non-schema value"), schema_name, key);
545
546          if (schema_namep)
547            *schema_namep = schema_name;
548          else
549            g_free (schema_name);
550
551          return NULL;
552        }
553      else if (val != NULL)
554        {
555          GConfValue* retval = gconf_value_get_schema(val)->default_value;
556          /* cheat, "unparent" the value to avoid a copy */
557          gconf_value_get_schema(val)->default_value = NULL;
558          gconf_value_free(val);
559
560          if (schema_namep)
561            *schema_namep = schema_name;
562          else
563            g_free (schema_name);
564         
565          return retval;
566        }
567      else
568        {
569          if (schema_namep)
570            *schema_namep = schema_name;
571          else
572            g_free (schema_name);
573         
574          return NULL;
575        }
576    }
577 
578  return NULL;
579}
580
581void
582gconf_sources_set_value   (GConfSources* sources,
583                           const gchar* key,
584                           GConfValue* value,
585                           GError** err)
586{
587  GList* tmp;
588
589  g_return_if_fail(sources != NULL);
590  g_return_if_fail(key != NULL);
591  g_return_if_fail((err == NULL) || (*err == NULL));
592 
593  if (!gconf_key_check(key, err))
594    return;
595 
596  g_assert(*key != '\0');
597 
598  if (key[1] == '\0')
599    {
600      gconf_set_error(err, GCONF_ERROR_IS_DIR,
601                      _("The '/' name can only be a directory, not a key"));
602      return;
603    }
604 
605  tmp = sources->sources;
606
607  while (tmp != NULL)
608    {
609      GConfSource* src = tmp->data;
610
611      if (gconf_source_set_value(src, key, value, err))
612        {
613          /* source was writable */
614          return;
615        }
616      else
617        {
618          /* check whether the value is set; if it is, then
619             we return an error since setting an overridden value
620             would have no effect
621          */
622          GConfValue* val;
623
624          val = gconf_source_query_value(tmp->data, key, NULL, NULL, NULL);
625         
626          if (val != NULL)
627            {
628              gconf_value_free(val);
629              gconf_set_error(err, GCONF_ERROR_OVERRIDDEN,
630                              _("Value for `%s' set in a read-only source at the front of your configuration path."), key);
631              return;
632            }
633        }
634
635      tmp = g_list_next(tmp);
636    }
637
638  /* If we arrived here, then there was nowhere to write a value */
639  g_set_error (err,
640               GCONF_ERROR,
641               GCONF_ERROR_NO_WRITABLE_DATABASE,
642               _("Unable to store a value at key '%s', as the configuration server has no writeable databases. There are two common causes of this problem: 1) your configuration path file doesn't contain any databases or wasn't found or 2) somehow we mistakenly created two gconfd processes. 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. 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? As always, check the user.* syslog for details on problems gconfd encountered."),
643               key);
644}
645
646void
647gconf_sources_unset_value   (GConfSources* sources,
648                             const gchar* key,
649                             const gchar* locale,
650                             GError** err)
651{
652  /* We unset in every layer we can write to... */
653  GList* tmp;
654  GError* error = NULL;
655 
656  tmp = sources->sources;
657
658  while (tmp != NULL)
659    {
660      GConfSource* src = tmp->data;
661
662      if (gconf_source_unset_value(src, key, locale, &error))
663        {
664          /* it was writable */
665
666          /* On error, set error and bail */
667          if (error != NULL)
668            {
669              if (err)
670                {
671                  g_return_if_fail(*err == NULL);
672                  *err = error;
673                  return;
674                }
675              else
676                {
677                  g_error_free(error);
678                  return;
679                }
680            }
681        }
682     
683      tmp = g_list_next(tmp);
684    }
685}
686
687gboolean
688gconf_sources_dir_exists (GConfSources* sources,
689                          const gchar* dir,
690                          GError** err)
691{
692  GList *tmp;
693
694  if (!gconf_key_check(dir, err))
695    return FALSE;
696 
697  tmp = sources->sources;
698 
699  while (tmp != NULL)
700    {
701      GConfSource* src = tmp->data;
702     
703      if (gconf_source_dir_exists (src, dir, err))
704        return TRUE;
705
706      tmp = g_list_next(tmp);
707    }
708 
709  return FALSE;
710}
711         
712void         
713gconf_sources_remove_dir (GConfSources* sources,
714                          const gchar* dir,
715                          GError** err)
716{
717  /* We remove in every layer we can write to... */
718  GList* tmp;
719 
720  if (!gconf_key_check(dir, err))
721    return;
722 
723  tmp = sources->sources;
724
725  while (tmp != NULL)
726    {
727      GConfSource* src = tmp->data;
728      GError* error = NULL;
729     
730      gconf_source_remove_dir(src, dir, &error);
731
732      /* On error, set error and bail */
733      if (error != NULL)
734        {
735          if (err)
736            {
737              g_return_if_fail(*err == NULL);
738              *err = error;
739              return;
740            }
741          else
742            {
743              g_error_free(error);
744              return;
745            }
746        }
747     
748      tmp = g_list_next(tmp);
749    }
750}
751
752void         
753gconf_sources_set_schema        (GConfSources* sources,
754                                 const gchar* key,
755                                 const gchar* schema_key,
756                                 GError** err)
757{
758  GList* tmp;
759
760  if (!gconf_key_check(key, err))
761    return;
762
763  if (!gconf_key_check(schema_key, err))
764    return;
765 
766  tmp = sources->sources;
767
768  while (tmp != NULL)
769    {
770      GConfSource* src = tmp->data;
771
772      /* may set error, we just leave its setting */
773      /* returns TRUE if the source was writable */
774      if (gconf_source_set_schema(src, key, schema_key, err))
775        return;
776
777      tmp = g_list_next(tmp);
778    }
779}
780
781/* God, this is depressingly inefficient. Maybe there's a nicer way to
782   implement it... */
783/* Then we have to ship it all to the app via CORBA... */
784/* Anyway, we use a hash to be sure we have a single value for
785   each key in the directory, and we always take that value from
786   the first source that had one set. When we're done we flatten
787   the hash.
788*/
789static void
790hash_listify_func(gpointer key, gpointer value, gpointer user_data)
791{
792  GSList** list_p = user_data;
793
794  *list_p = g_slist_prepend(*list_p, value);
795}
796
797static void
798hash_destroy_entries_func(gpointer key, gpointer value, gpointer user_data)
799{
800  GConfEntry* entry;
801
802  entry = value;
803
804  gconf_entry_free(entry);
805}
806
807static void
808hash_destroy_pointers_func(gpointer key, gpointer value, gpointer user_data)
809{
810  g_free(value);
811}
812
813struct DefaultsLookupData {
814  GConfSources* sources;
815  const gchar** locales;
816};
817
818static void
819hash_lookup_defaults_func(gpointer key, gpointer value, gpointer user_data)
820{
821  GConfEntry *entry = value;
822  struct DefaultsLookupData* dld = user_data;
823  GConfSources *sources = dld->sources;
824  const gchar** locales = dld->locales;
825 
826  if (gconf_entry_get_value(entry) == NULL)
827    {
828      if (gconf_entry_get_schema_name(entry) != NULL)
829        {
830          GConfValue *val;
831
832
833          val = gconf_sources_query_value(sources,
834                                          gconf_entry_get_schema_name(entry),
835                                          locales,
836                                          TRUE,
837                                          NULL,
838                                          NULL,
839                                          NULL,
840                                          NULL);
841
842          if (val != NULL &&
843              val->type == GCONF_VALUE_SCHEMA)
844            {
845              GConfValue* defval = gconf_value_get_schema(val)->default_value;
846              /* cheat, "unparent" the value to avoid a copy */
847              gconf_value_get_schema(val)->default_value = NULL;
848
849              gconf_entry_set_value_nocopy(entry, defval);
850              gconf_entry_set_is_default(entry, TRUE);
851            }
852
853          if (val)
854            gconf_value_free(val);
855        }
856    }
857}
858
859
860static gboolean
861key_is_writable (GConfSources *sources,
862                 GConfSource  *value_in_src,
863                 const gchar *key,
864                 GError **err)
865{
866  GList *tmp;
867 
868  tmp = sources->sources;
869
870  while (tmp != NULL)
871    {
872      GConfSource* src;
873     
874      src = tmp->data;
875     
876      if (source_is_writable (src, key, NULL))
877        return TRUE;
878
879      if (src == value_in_src)
880        return FALSE; /* didn't find a writable source before value-containing
881                         source.
882                      */
883     
884      tmp = g_list_next (tmp);
885    }
886
887  /* This shouldn't be reached actually */
888  return FALSE;
889}
890
891GSList*       
892gconf_sources_all_entries   (GConfSources* sources,
893                             const gchar* dir,
894                             const gchar** locales,
895                             GError** err)
896{
897  GList* tmp;
898  GHashTable* hash;
899  GSList* flattened;
900  gboolean first_pass = TRUE; /* as an optimization, don't bother
901                                 doing hash lookups on first source
902                              */
903  struct DefaultsLookupData dld = { NULL, NULL };
904 
905  dld.sources = sources;
906  dld.locales = locales;
907
908  /* Empty GConfSources, skip it */
909  if (sources->sources == NULL)
910    return NULL;
911
912  hash = g_hash_table_new(g_str_hash, g_str_equal);
913
914  tmp = sources->sources;
915
916  while (tmp != NULL)
917    {
918      GConfSource* src;
919      GSList* pairs;
920      GSList* iter;
921      GError* error = NULL;
922     
923      src   = tmp->data;
924      pairs = gconf_source_all_entries(src, dir, locales, &error);
925      iter  = pairs;
926     
927      /* On error, set error and bail */
928      if (error != NULL)
929        {
930          g_hash_table_foreach(hash, hash_destroy_entries_func, NULL);
931         
932          g_hash_table_destroy(hash);
933         
934          if (err)
935            {
936              g_return_val_if_fail(*err == NULL, NULL);
937              *err = error;
938              return NULL;
939            }
940          else
941            {
942              g_error_free(error);
943              return NULL;
944            }
945        }
946
947      /* Iterate over the list of entries, stuffing them in the hash
948         and setting their writability flag if they're new
949      */
950     
951      while (iter != NULL)
952        {
953          GConfEntry* pair = iter->data;
954          GConfEntry* previous;
955          gchar *full;
956         
957          if (first_pass)
958            previous = NULL; /* Can't possibly be there. */
959          else
960            previous = g_hash_table_lookup(hash, pair->key);
961         
962          if (previous != NULL)
963            {
964              if (gconf_entry_get_value (previous) != NULL)
965                /* Discard this latest one */
966                ;
967              else
968                {
969                  /* Save the new value, previously we had an entry but no value */
970                  gconf_entry_set_value_nocopy (previous,
971                                                gconf_entry_steal_value(pair));
972
973                  /* As an efficiency hack, remember that
974                   * entry->key is relative not absolute on the
975                   * gconfd side
976                   */
977                  full = gconf_concat_dir_and_key (dir, previous->key);
978                 
979                  previous->is_writable = key_is_writable (sources,
980                                                           src,
981                                                           full,
982                                                           NULL);
983
984                  g_free (full);
985                }
986             
987              gconf_entry_free(pair);
988            }
989          else
990            {
991              /* Save */
992              g_hash_table_insert(hash, pair->key, pair);
993             
994              /* As an efficiency hack, remember that
995               * entry->key is relative not absolute on the
996               * gconfd side
997               */
998              full = gconf_concat_dir_and_key (dir, pair->key);
999             
1000              pair->is_writable = key_is_writable (sources,
1001                                                   src,
1002                                                   full,
1003                                                   NULL);
1004             
1005              g_free (full);
1006            }
1007
1008          iter = g_slist_next(iter);
1009        }
1010     
1011      /* All pairs are either stored or destroyed. */
1012      g_slist_free(pairs);
1013
1014      first_pass = FALSE;
1015
1016      tmp = g_list_next(tmp);
1017    }
1018
1019  flattened = NULL;
1020
1021  g_hash_table_foreach(hash, hash_lookup_defaults_func, &dld);
1022 
1023  g_hash_table_foreach(hash, hash_listify_func, &flattened);
1024
1025  g_hash_table_destroy(hash);
1026 
1027  return flattened;
1028}
1029
1030GSList*       
1031gconf_sources_all_dirs   (GConfSources* sources,
1032                          const gchar* dir,
1033                          GError** err)
1034{
1035  GList* tmp = NULL;
1036  GHashTable* hash = NULL;
1037  GSList* flattened = NULL;
1038  gboolean first_pass = TRUE; /* as an optimization, don't bother
1039                                 doing hash lookups on first source
1040                              */
1041
1042  g_return_val_if_fail(sources != NULL, NULL);
1043  g_return_val_if_fail(dir != NULL, NULL);
1044
1045  /* As another optimization, skip the whole
1046     hash thing if there's only zero or one sources
1047  */
1048  if (sources->sources == NULL)
1049    return NULL;
1050
1051  if (sources->sources->next == NULL)
1052    {
1053      return gconf_source_all_dirs (sources->sources->data, dir, err);
1054    }
1055
1056  /* 2 or more sources */
1057  g_assert(g_list_length(sources->sources) > 1);
1058
1059  hash = g_hash_table_new(g_str_hash, g_str_equal);
1060
1061  tmp = sources->sources;
1062
1063  while (tmp != NULL)
1064    {
1065      GConfSource* src;
1066      GSList* subdirs;
1067      GSList* iter;
1068      GError* error = NULL;
1069     
1070      src     = tmp->data;
1071      subdirs = gconf_source_all_dirs(src, dir, &error);
1072      iter    = subdirs;
1073
1074      /* On error, set error and bail */
1075      if (error != NULL)
1076        {
1077          g_hash_table_foreach (hash, hash_destroy_pointers_func, NULL);
1078         
1079          g_hash_table_destroy (hash);
1080         
1081          if (err)
1082            {
1083              g_return_val_if_fail(*err == NULL, NULL);
1084              *err = error;
1085              return NULL;
1086            }
1087          else
1088            {
1089              g_error_free(error);
1090              return NULL;
1091            }
1092        }
1093     
1094      while (iter != NULL)
1095        {
1096          gchar* subdir = iter->data;
1097          gchar* previous;
1098         
1099          if (first_pass)
1100            previous = NULL; /* Can't possibly be there. */
1101          else
1102            previous = g_hash_table_lookup(hash, subdir);
1103         
1104          if (previous != NULL)
1105            {
1106              /* Discard */
1107              g_free(subdir);
1108            }
1109          else
1110            {
1111              /* Save */
1112              g_hash_table_insert(hash, subdir, subdir);
1113            }
1114
1115          iter = g_slist_next(iter);
1116        }
1117     
1118      /* All pairs are either stored or destroyed. */
1119      g_slist_free(subdirs);
1120
1121      first_pass = FALSE;
1122
1123      tmp = g_list_next(tmp);
1124    }
1125
1126  flattened = NULL;
1127
1128  g_hash_table_foreach(hash, hash_listify_func, &flattened);
1129
1130  g_hash_table_destroy(hash);
1131
1132  return flattened;
1133}
1134
1135gboolean
1136gconf_sources_sync_all    (GConfSources* sources, GError** err)
1137{
1138  GList* tmp;
1139  gboolean failed = FALSE;
1140  GError* all_errors = NULL;
1141 
1142  tmp = sources->sources;
1143
1144  while (tmp != NULL)
1145    {
1146      GConfSource* src = tmp->data;
1147      GError* error = NULL;
1148     
1149      if (!gconf_source_sync_all(src, &error))
1150        {
1151          failed = TRUE;
1152          g_assert(error != NULL);
1153        }
1154         
1155      /* On error, set error and bail */
1156      if (error != NULL)
1157        {
1158          if (err)
1159            all_errors = gconf_compose_errors(all_errors, error);
1160
1161          g_error_free(error);
1162        }
1163         
1164      tmp = g_list_next(tmp);
1165    }
1166
1167  if (err)
1168    {
1169      g_return_val_if_fail(*err == NULL, !failed);
1170      *err = all_errors;
1171    }
1172 
1173  return !failed;
1174}
1175
1176GConfMetaInfo*
1177gconf_sources_query_metainfo (GConfSources* sources,
1178                              const gchar* key,
1179                              GError** err)
1180{
1181  GList* tmp;
1182  GConfMetaInfo* mi = NULL;
1183 
1184  tmp = sources->sources;
1185
1186  while (tmp != NULL)
1187    {
1188      GConfSource* src = tmp->data;
1189      GError* error = NULL;
1190      GConfMetaInfo* this_mi;
1191
1192      this_mi = gconf_source_query_metainfo(src, key, &error);
1193     
1194      /* On error, just keep going, log the error maybe. */
1195      if (error != NULL)
1196        {
1197          g_assert(this_mi == NULL);
1198          gconf_log(GCL_ERR, _("Error finding metainfo: %s"), error->message);
1199          g_error_free(error);
1200          error = NULL;
1201        }
1202
1203      if (this_mi != NULL)
1204        {
1205          if (mi == NULL)
1206            mi = this_mi;
1207          else
1208            {
1209              /* Fill in any missing fields of "mi" found in "this_mi",
1210                 and pick the most recent mod time */
1211              if (gconf_meta_info_get_schema(mi) == NULL &&
1212                  gconf_meta_info_get_schema(this_mi) != NULL)
1213                {
1214                  gconf_meta_info_set_schema(mi,
1215                                             gconf_meta_info_get_schema(mi));
1216                }
1217
1218              if (gconf_meta_info_get_mod_user(mi) == NULL &&
1219                  gconf_meta_info_get_mod_user(this_mi) != NULL)
1220                {
1221                  gconf_meta_info_set_mod_user(mi,
1222                                               gconf_meta_info_get_mod_user(this_mi));
1223                }
1224             
1225              if (gconf_meta_info_mod_time(mi) < gconf_meta_info_mod_time(this_mi))
1226                {
1227                  gconf_meta_info_set_mod_time(mi,
1228                                               gconf_meta_info_mod_time(this_mi));
1229                }
1230
1231              gconf_meta_info_free(this_mi);
1232            }
1233        }
1234     
1235      tmp = g_list_next(tmp);
1236    }
1237
1238  return mi;
1239}
1240
1241GConfValue*
1242gconf_sources_query_default_value(GConfSources* sources,
1243                                  const gchar* key,
1244                                  const gchar** locales,
1245                                  gboolean* is_writable,
1246                                  GError** err)
1247{
1248  GError* error = NULL;
1249  GConfValue* val;
1250  GConfMetaInfo* mi;
1251 
1252  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1253
1254  if (is_writable)
1255    *is_writable = key_is_writable (sources, NULL, key, NULL);
1256 
1257  mi = gconf_sources_query_metainfo(sources, key,
1258                                    &error);
1259  if (mi == NULL)
1260    {
1261      if (error != NULL)
1262        {
1263          if (err)
1264            *err = error;
1265          else
1266            {
1267              gconf_log(GCL_ERR, _("Error getting metainfo: %s"), error->message);
1268              g_error_free(error);
1269            }
1270        }
1271      return NULL;
1272    }
1273
1274  if (gconf_meta_info_get_schema(mi) == NULL)
1275    {
1276      gconf_meta_info_free(mi);
1277      return NULL;
1278    }
1279     
1280  val = gconf_sources_query_value(sources,
1281                                  gconf_meta_info_get_schema(mi), locales,
1282                                  TRUE, NULL, NULL, NULL, &error);
1283 
1284  if (val != NULL)
1285    {
1286      GConfSchema* schema;
1287
1288      if (val->type != GCONF_VALUE_SCHEMA)
1289        {
1290          gconf_log(GCL_WARNING,
1291                    _("Key `%s' listed as schema for key `%s' actually stores type `%s'"),
1292                    gconf_meta_info_get_schema(mi),
1293                    key,
1294                    gconf_value_type_to_string(val->type));
1295
1296          gconf_meta_info_free(mi);
1297          return NULL;
1298        }
1299
1300      gconf_meta_info_free(mi);
1301
1302      schema = gconf_value_get_schema(val);
1303      val->d.schema_data = NULL; /* cheat, steal schema from the GConfValue */
1304     
1305      gconf_value_free(val); /* schema not destroyed due to our cheat */
1306     
1307      if (schema != NULL)
1308        {
1309          GConfValue* retval;
1310          /* Cheat, steal value from schema */
1311          retval = schema->default_value;
1312          schema->default_value = NULL;
1313
1314          gconf_schema_free(schema);
1315         
1316          return retval;
1317        }
1318      return NULL;
1319    }
1320  else
1321    {
1322      if (error != NULL)
1323        {
1324          if (err)
1325            *err = error;
1326          else
1327            {
1328              gconf_log(GCL_ERR, _("Error getting value for `%s': %s"),
1329                        gconf_meta_info_get_schema(mi),
1330                        error->message);
1331              g_error_free(error);
1332            }
1333        }
1334     
1335      gconf_meta_info_free(mi);
1336     
1337      return NULL;
1338    }
1339}
Note: See TracBrowser for help on using the repository browser.