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 | |
---|
40 | GConfSource* |
---|
41 | gconf_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 | |
---|
72 | void |
---|
73 | gconf_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 | |
---|
92 | static gboolean |
---|
93 | source_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 | |
---|
106 | static GConfValue* |
---|
107 | gconf_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 | |
---|
128 | static GConfMetaInfo* |
---|
129 | gconf_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 */ |
---|
150 | static gboolean |
---|
151 | gconf_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 | |
---|
173 | static gboolean |
---|
174 | gconf_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 | |
---|
194 | static GSList* |
---|
195 | gconf_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 | |
---|
213 | static GSList* |
---|
214 | gconf_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 | |
---|
231 | static gboolean |
---|
232 | gconf_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 | |
---|
249 | static void |
---|
250 | gconf_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 | |
---|
265 | static gboolean |
---|
266 | gconf_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 | |
---|
286 | static gboolean |
---|
287 | gconf_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 | |
---|
296 | GConfSources* |
---|
297 | gconf_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 | |
---|
334 | GConfSources* |
---|
335 | gconf_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 | |
---|
346 | void |
---|
347 | gconf_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 | |
---|
365 | void |
---|
366 | gconf_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 | |
---|
383 | GConfValue* |
---|
384 | gconf_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 | |
---|
581 | void |
---|
582 | gconf_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 | |
---|
646 | void |
---|
647 | gconf_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 | |
---|
687 | gboolean |
---|
688 | gconf_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 | |
---|
712 | void |
---|
713 | gconf_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 | |
---|
752 | void |
---|
753 | gconf_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 | */ |
---|
789 | static void |
---|
790 | hash_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 | |
---|
797 | static void |
---|
798 | hash_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 | |
---|
807 | static void |
---|
808 | hash_destroy_pointers_func(gpointer key, gpointer value, gpointer user_data) |
---|
809 | { |
---|
810 | g_free(value); |
---|
811 | } |
---|
812 | |
---|
813 | struct DefaultsLookupData { |
---|
814 | GConfSources* sources; |
---|
815 | const gchar** locales; |
---|
816 | }; |
---|
817 | |
---|
818 | static void |
---|
819 | hash_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 | |
---|
860 | static gboolean |
---|
861 | key_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 | |
---|
891 | GSList* |
---|
892 | gconf_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 | |
---|
1030 | GSList* |
---|
1031 | gconf_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 | |
---|
1135 | gboolean |
---|
1136 | gconf_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 | |
---|
1176 | GConfMetaInfo* |
---|
1177 | gconf_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 | |
---|
1241 | GConfValue* |
---|
1242 | gconf_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 | } |
---|