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-internals.h"
23 #include "gconf-backend.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 #include <locale.h>
36 #include <time.h>
37 #include <math.h>
38
39 #include <gio/gio.h>
40
41 #ifdef G_OS_WIN32
42 #include <windows.h>
43 #include <share.h>
44 #define pipe(fds) _pipe(fds, 4096, _O_BINARY)
45 #endif
46
47 gboolean gconf_log_debug_messages = FALSE;
48
49 static gboolean gconf_daemon_mode = FALSE;
50 static gchar* daemon_ior = NULL;
51
52 void
gconf_set_daemon_mode(gboolean setting)53 gconf_set_daemon_mode(gboolean setting)
54 {
55 gconf_daemon_mode = setting;
56 }
57
58 gboolean
gconf_in_daemon_mode(void)59 gconf_in_daemon_mode(void)
60 {
61 return gconf_daemon_mode;
62 }
63
64 void
gconf_set_daemon_ior(const gchar * ior)65 gconf_set_daemon_ior(const gchar* ior)
66 {
67 if (daemon_ior != NULL)
68 {
69 g_free(daemon_ior);
70 daemon_ior = NULL;
71 }
72
73 if (ior != NULL)
74 daemon_ior = g_strdup(ior);
75 }
76
77 const gchar*
gconf_get_daemon_ior(void)78 gconf_get_daemon_ior(void)
79 {
80 return daemon_ior;
81 }
82
83 gchar*
gconf_key_directory(const gchar * key)84 gconf_key_directory (const gchar* key)
85 {
86 const gchar* end;
87 gchar* retval;
88 int len;
89
90 end = strrchr(key, '/');
91
92 if (end == NULL)
93 {
94 gconf_log(GCL_ERR, _("No '/' in key \"%s\""), key);
95 return NULL;
96 }
97
98 len = end-key+1;
99
100 if (len == 1)
101 {
102 /* Root directory */
103 retval = g_strdup("/");
104 }
105 else
106 {
107 retval = g_malloc(len);
108
109 strncpy(retval, key, len);
110
111 retval[len-1] = '\0';
112 }
113
114 return retval;
115 }
116
117 const gchar*
gconf_key_key(const gchar * key)118 gconf_key_key (const gchar* key)
119 {
120 const gchar* end;
121
122 end = strrchr(key, '/');
123
124 if (end != NULL)
125 ++end;
126
127 return end;
128 }
129
130 /*
131 * Random stuff
132 */
133
134 #if HAVE_CORBA
135 GConfValue*
gconf_value_from_corba_value(const ConfigValue * value)136 gconf_value_from_corba_value(const ConfigValue* value)
137 {
138 GConfValue* gval;
139 GConfValueType type = GCONF_VALUE_INVALID;
140
141 switch (value->_d)
142 {
143 case InvalidVal:
144 return NULL;
145 case IntVal:
146 type = GCONF_VALUE_INT;
147 break;
148 case StringVal:
149 type = GCONF_VALUE_STRING;
150 break;
151 case FloatVal:
152 type = GCONF_VALUE_FLOAT;
153 break;
154 case BoolVal:
155 type = GCONF_VALUE_BOOL;
156 break;
157 case SchemaVal:
158 type = GCONF_VALUE_SCHEMA;
159 break;
160 case ListVal:
161 type = GCONF_VALUE_LIST;
162 break;
163 case PairVal:
164 type = GCONF_VALUE_PAIR;
165 break;
166 default:
167 gconf_log(GCL_DEBUG, "Invalid type in %s", G_STRFUNC);
168 return NULL;
169 }
170
171 g_assert(GCONF_VALUE_TYPE_VALID(type));
172
173 gval = gconf_value_new(type);
174
175 switch (gval->type)
176 {
177 case GCONF_VALUE_INT:
178 gconf_value_set_int(gval, value->_u.int_value);
179 break;
180 case GCONF_VALUE_STRING:
181 if (!g_utf8_validate (value->_u.string_value, -1, NULL))
182 {
183 gconf_log (GCL_ERR, _("Invalid UTF-8 in string value in '%s'"),
184 value->_u.string_value);
185 }
186 else
187 {
188 gconf_value_set_string(gval, value->_u.string_value);
189 }
190 break;
191 case GCONF_VALUE_FLOAT:
192 gconf_value_set_float(gval, value->_u.float_value);
193 break;
194 case GCONF_VALUE_BOOL:
195 gconf_value_set_bool(gval, value->_u.bool_value);
196 break;
197 case GCONF_VALUE_SCHEMA:
198 gconf_value_set_schema_nocopy(gval,
199 gconf_schema_from_corba_schema(&(value->_u.schema_value)));
200 break;
201 case GCONF_VALUE_LIST:
202 {
203 GSList* list = NULL;
204 guint i = 0;
205
206 switch (value->_u.list_value.list_type)
207 {
208 case BIntVal:
209 gconf_value_set_list_type(gval, GCONF_VALUE_INT);
210 break;
211 case BBoolVal:
212 gconf_value_set_list_type(gval, GCONF_VALUE_BOOL);
213 break;
214 case BFloatVal:
215 gconf_value_set_list_type(gval, GCONF_VALUE_FLOAT);
216 break;
217 case BStringVal:
218 gconf_value_set_list_type(gval, GCONF_VALUE_STRING);
219 break;
220 case BInvalidVal:
221 break;
222 default:
223 g_warning("Bizarre list type in %s", G_STRFUNC);
224 break;
225 }
226
227 if (gconf_value_get_list_type(gval) != GCONF_VALUE_INVALID)
228 {
229 i = 0;
230 while (i < value->_u.list_value.seq._length)
231 {
232 GConfValue* val;
233
234 /* This is a bit dubious; we cast a ConfigBasicValue to ConfigValue
235 because they have the same initial members, but by the time
236 the CORBA and C specs kick in, not sure we are guaranteed
237 to be able to do this.
238 */
239 val = gconf_value_from_corba_value((ConfigValue*)&value->_u.list_value.seq._buffer[i]);
240
241 if (val == NULL)
242 gconf_log(GCL_ERR, _("Couldn't interpret CORBA value for list element"));
243 else if (val->type != gconf_value_get_list_type(gval))
244 gconf_log(GCL_ERR, _("Incorrect type for list element in %s"), G_STRFUNC);
245 else
246 list = g_slist_prepend(list, val);
247
248 ++i;
249 }
250
251 list = g_slist_reverse(list);
252
253 gconf_value_set_list_nocopy(gval, list);
254 }
255 else
256 {
257 gconf_log(GCL_ERR, _("Received list from gconfd with a bad list type"));
258 }
259 }
260 break;
261 case GCONF_VALUE_PAIR:
262 {
263 g_return_val_if_fail(value->_u.pair_value._length == 2, gval);
264
265 gconf_value_set_car_nocopy(gval,
266 gconf_value_from_corba_value((ConfigValue*)&value->_u.list_value.seq._buffer[0]));
267
268 gconf_value_set_cdr_nocopy(gval,
269 gconf_value_from_corba_value((ConfigValue*)&value->_u.list_value.seq._buffer[1]));
270 }
271 break;
272 default:
273 g_assert_not_reached();
274 break;
275 }
276
277 return gval;
278 }
279
280 void
gconf_fill_corba_value_from_gconf_value(const GConfValue * value,ConfigValue * cv)281 gconf_fill_corba_value_from_gconf_value(const GConfValue *value,
282 ConfigValue *cv)
283 {
284 if (value == NULL)
285 {
286 cv->_d = InvalidVal;
287 return;
288 }
289
290 switch (value->type)
291 {
292 case GCONF_VALUE_INT:
293 cv->_d = IntVal;
294 cv->_u.int_value = gconf_value_get_int(value);
295 break;
296 case GCONF_VALUE_STRING:
297 cv->_d = StringVal;
298 cv->_u.string_value = CORBA_string_dup((char*)gconf_value_get_string(value));
299 break;
300 case GCONF_VALUE_FLOAT:
301 cv->_d = FloatVal;
302 cv->_u.float_value = gconf_value_get_float(value);
303 break;
304 case GCONF_VALUE_BOOL:
305 cv->_d = BoolVal;
306 cv->_u.bool_value = gconf_value_get_bool(value);
307 break;
308 case GCONF_VALUE_SCHEMA:
309 cv->_d = SchemaVal;
310 gconf_fill_corba_schema_from_gconf_schema (gconf_value_get_schema(value),
311 &cv->_u.schema_value);
312 break;
313 case GCONF_VALUE_LIST:
314 {
315 guint n, i;
316 GSList* list;
317
318 cv->_d = ListVal;
319
320 list = gconf_value_get_list(value);
321
322 n = g_slist_length(list);
323
324 cv->_u.list_value.seq._buffer =
325 CORBA_sequence_ConfigBasicValue_allocbuf(n);
326 cv->_u.list_value.seq._length = n;
327 cv->_u.list_value.seq._maximum = n;
328 CORBA_sequence_set_release(&cv->_u.list_value.seq, TRUE);
329
330 switch (gconf_value_get_list_type(value))
331 {
332 case GCONF_VALUE_INT:
333 cv->_u.list_value.list_type = BIntVal;
334 break;
335
336 case GCONF_VALUE_BOOL:
337 cv->_u.list_value.list_type = BBoolVal;
338 break;
339
340 case GCONF_VALUE_STRING:
341 cv->_u.list_value.list_type = BStringVal;
342 break;
343
344 case GCONF_VALUE_FLOAT:
345 cv->_u.list_value.list_type = BFloatVal;
346 break;
347
348 case GCONF_VALUE_SCHEMA:
349 cv->_u.list_value.list_type = BSchemaVal;
350 break;
351
352 default:
353 cv->_u.list_value.list_type = BInvalidVal;
354 gconf_log(GCL_DEBUG, "Invalid list type in %s", G_STRFUNC);
355 break;
356 }
357
358 i= 0;
359 while (list != NULL)
360 {
361 /* That dubious ConfigBasicValue->ConfigValue cast again */
362 gconf_fill_corba_value_from_gconf_value((GConfValue*)list->data,
363 (ConfigValue*)&cv->_u.list_value.seq._buffer[i]);
364
365 list = g_slist_next(list);
366 ++i;
367 }
368 }
369 break;
370 case GCONF_VALUE_PAIR:
371 {
372 cv->_d = PairVal;
373
374 cv->_u.pair_value._buffer =
375 CORBA_sequence_ConfigBasicValue_allocbuf(2);
376 cv->_u.pair_value._length = 2;
377 cv->_u.pair_value._maximum = 2;
378 CORBA_sequence_set_release(&cv->_u.pair_value, TRUE);
379
380 /* dubious cast */
381 gconf_fill_corba_value_from_gconf_value (gconf_value_get_car(value),
382 (ConfigValue*)&cv->_u.pair_value._buffer[0]);
383 gconf_fill_corba_value_from_gconf_value(gconf_value_get_cdr(value),
384 (ConfigValue*)&cv->_u.pair_value._buffer[1]);
385 }
386 break;
387
388 case GCONF_VALUE_INVALID:
389 cv->_d = InvalidVal;
390 break;
391 default:
392 cv->_d = InvalidVal;
393 gconf_log(GCL_DEBUG, "Unknown type in %s", G_STRFUNC);
394 break;
395 }
396 }
397
398 ConfigValue*
gconf_corba_value_from_gconf_value(const GConfValue * value)399 gconf_corba_value_from_gconf_value (const GConfValue* value)
400 {
401 ConfigValue* cv;
402
403 cv = ConfigValue__alloc();
404
405 gconf_fill_corba_value_from_gconf_value(value, cv);
406
407 return cv;
408 }
409
410 ConfigValue*
gconf_invalid_corba_value(void)411 gconf_invalid_corba_value (void)
412 {
413 ConfigValue* cv;
414
415 cv = ConfigValue__alloc();
416
417 cv->_d = InvalidVal;
418
419 return cv;
420 }
421
422 gchar*
gconf_object_to_string(CORBA_Object obj,GError ** err)423 gconf_object_to_string (CORBA_Object obj,
424 GError **err)
425 {
426 CORBA_Environment ev;
427 gchar *ior;
428 gchar *retval;
429
430 CORBA_exception_init (&ev);
431
432 ior = CORBA_ORB_object_to_string (gconf_orb_get (), obj, &ev);
433
434 if (ior == NULL)
435 {
436 gconf_set_error (err,
437 GCONF_ERROR_FAILED,
438 _("Failed to convert object to IOR"));
439
440 return NULL;
441 }
442
443 retval = g_strdup (ior);
444
445 CORBA_free (ior);
446
447 return retval;
448 }
449
450 static ConfigValueType
corba_type_from_gconf_type(GConfValueType type)451 corba_type_from_gconf_type(GConfValueType type)
452 {
453 switch (type)
454 {
455 case GCONF_VALUE_INT:
456 return IntVal;
457 case GCONF_VALUE_BOOL:
458 return BoolVal;
459 case GCONF_VALUE_FLOAT:
460 return FloatVal;
461 case GCONF_VALUE_INVALID:
462 return InvalidVal;
463 case GCONF_VALUE_STRING:
464 return StringVal;
465 case GCONF_VALUE_SCHEMA:
466 return SchemaVal;
467 case GCONF_VALUE_LIST:
468 return ListVal;
469 case GCONF_VALUE_PAIR:
470 return PairVal;
471 default:
472 g_assert_not_reached();
473 return InvalidVal;
474 }
475 }
476
477 static GConfValueType
gconf_type_from_corba_type(ConfigValueType type)478 gconf_type_from_corba_type(ConfigValueType type)
479 {
480 switch (type)
481 {
482 case InvalidVal:
483 return GCONF_VALUE_INVALID;
484 case StringVal:
485 return GCONF_VALUE_STRING;
486 case IntVal:
487 return GCONF_VALUE_INT;
488 case FloatVal:
489 return GCONF_VALUE_FLOAT;
490 case SchemaVal:
491 return GCONF_VALUE_SCHEMA;
492 case BoolVal:
493 return GCONF_VALUE_BOOL;
494 case ListVal:
495 return GCONF_VALUE_LIST;
496 case PairVal:
497 return GCONF_VALUE_PAIR;
498 default:
499 g_assert_not_reached();
500 return GCONF_VALUE_INVALID;
501 }
502 }
503
504 void
gconf_fill_corba_schema_from_gconf_schema(const GConfSchema * sc,ConfigSchema * cs)505 gconf_fill_corba_schema_from_gconf_schema(const GConfSchema *sc,
506 ConfigSchema *cs)
507 {
508 cs->value_type = corba_type_from_gconf_type (gconf_schema_get_type (sc));
509 cs->value_list_type = corba_type_from_gconf_type (gconf_schema_get_list_type (sc));
510 cs->value_car_type = corba_type_from_gconf_type (gconf_schema_get_car_type (sc));
511 cs->value_cdr_type = corba_type_from_gconf_type (gconf_schema_get_cdr_type (sc));
512
513 cs->locale = CORBA_string_dup (gconf_schema_get_locale (sc) ? gconf_schema_get_locale (sc) : "");
514 cs->short_desc = CORBA_string_dup (gconf_schema_get_short_desc (sc) ? gconf_schema_get_short_desc (sc) : "");
515 cs->long_desc = CORBA_string_dup (gconf_schema_get_long_desc (sc) ? gconf_schema_get_long_desc (sc) : "");
516 cs->owner = CORBA_string_dup (gconf_schema_get_owner (sc) ? gconf_schema_get_owner (sc) : "");
517
518 {
519 gchar* encoded;
520 GConfValue* default_val;
521
522 default_val = gconf_schema_get_default_value (sc);
523
524 if (default_val)
525 {
526 encoded = gconf_value_encode (default_val);
527
528 g_assert (encoded != NULL);
529
530 cs->encoded_default_value = CORBA_string_dup (encoded);
531
532 g_free (encoded);
533 }
534 else
535 cs->encoded_default_value = CORBA_string_dup ("");
536 }
537 }
538
539 ConfigSchema*
gconf_corba_schema_from_gconf_schema(const GConfSchema * sc)540 gconf_corba_schema_from_gconf_schema (const GConfSchema* sc)
541 {
542 ConfigSchema* cs;
543
544 cs = ConfigSchema__alloc ();
545
546 gconf_fill_corba_schema_from_gconf_schema (sc, cs);
547
548 return cs;
549 }
550
551 GConfSchema*
gconf_schema_from_corba_schema(const ConfigSchema * cs)552 gconf_schema_from_corba_schema(const ConfigSchema* cs)
553 {
554 GConfSchema* sc;
555 GConfValueType type = GCONF_VALUE_INVALID;
556 GConfValueType list_type = GCONF_VALUE_INVALID;
557 GConfValueType car_type = GCONF_VALUE_INVALID;
558 GConfValueType cdr_type = GCONF_VALUE_INVALID;
559
560 type = gconf_type_from_corba_type(cs->value_type);
561 list_type = gconf_type_from_corba_type(cs->value_list_type);
562 car_type = gconf_type_from_corba_type(cs->value_car_type);
563 cdr_type = gconf_type_from_corba_type(cs->value_cdr_type);
564
565 sc = gconf_schema_new();
566
567 gconf_schema_set_type(sc, type);
568 gconf_schema_set_list_type(sc, list_type);
569 gconf_schema_set_car_type(sc, car_type);
570 gconf_schema_set_cdr_type(sc, cdr_type);
571
572 if (*cs->locale != '\0')
573 {
574 if (!g_utf8_validate (cs->locale, -1, NULL))
575 gconf_log (GCL_ERR, _("Invalid UTF-8 in locale for schema"));
576 else
577 gconf_schema_set_locale(sc, cs->locale);
578 }
579
580 if (*cs->short_desc != '\0')
581 {
582 if (!g_utf8_validate (cs->short_desc, -1, NULL))
583 gconf_log (GCL_ERR, _("Invalid UTF-8 in short description for schema"));
584 else
585 gconf_schema_set_short_desc(sc, cs->short_desc);
586 }
587
588 if (*cs->long_desc != '\0')
589 {
590 if (!g_utf8_validate (cs->long_desc, -1, NULL))
591 gconf_log (GCL_ERR, _("Invalid UTF-8 in long description for schema"));
592 else
593 gconf_schema_set_long_desc(sc, cs->long_desc);
594 }
595
596 if (*cs->owner != '\0')
597 {
598 if (!g_utf8_validate (cs->owner, -1, NULL))
599 gconf_log (GCL_ERR, _("Invalid UTF-8 in owner for schema"));
600 else
601 gconf_schema_set_owner(sc, cs->owner);
602 }
603
604 {
605 GConfValue* val;
606
607 val = gconf_value_decode(cs->encoded_default_value);
608
609 if (val)
610 gconf_schema_set_default_value_nocopy(sc, val);
611 }
612
613 return sc;
614 }
615 #endif /* HAVE_CORBA */
616
617 const gchar*
gconf_value_type_to_string(GConfValueType type)618 gconf_value_type_to_string(GConfValueType type)
619 {
620 switch (type)
621 {
622 case GCONF_VALUE_INT:
623 return "int";
624 case GCONF_VALUE_STRING:
625 return "string";
626 case GCONF_VALUE_FLOAT:
627 return "float";
628 case GCONF_VALUE_BOOL:
629 return "bool";
630 case GCONF_VALUE_SCHEMA:
631 return "schema";
632 case GCONF_VALUE_LIST:
633 return "list";
634 case GCONF_VALUE_PAIR:
635 return "pair";
636 case GCONF_VALUE_INVALID:
637 return "*invalid*";
638 default:
639 g_assert_not_reached();
640 return NULL; /* for warnings */
641 }
642 }
643
644 GConfValueType
gconf_value_type_from_string(const gchar * type_str)645 gconf_value_type_from_string(const gchar* type_str)
646 {
647 if (strcmp(type_str, "int") == 0)
648 return GCONF_VALUE_INT;
649 else if (strcmp(type_str, "float") == 0)
650 return GCONF_VALUE_FLOAT;
651 else if (strcmp(type_str, "string") == 0)
652 return GCONF_VALUE_STRING;
653 else if (strcmp(type_str, "bool") == 0)
654 return GCONF_VALUE_BOOL;
655 else if (strcmp(type_str, "schema") == 0)
656 return GCONF_VALUE_SCHEMA;
657 else if (strcmp(type_str, "list") == 0)
658 return GCONF_VALUE_LIST;
659 else if (strcmp(type_str, "pair") == 0)
660 return GCONF_VALUE_PAIR;
661 else
662 return GCONF_VALUE_INVALID;
663 }
664
665 /*
666 * Configuration files (yikes! we can't store our configuration in GConf!)
667 */
668
669 static gchar*
unquote_string(gchar * s)670 unquote_string(gchar* s)
671 {
672 gchar* end;
673
674 /* Strip whitespace and first quote from front of string */
675 while (*s && (g_ascii_isspace(*s) || (*s == '"')))
676 ++s;
677
678 end = s;
679 while (*end)
680 ++end;
681
682 --end; /* one back from '\0' */
683
684 /* Strip whitespace and last quote from end of string */
685 while ((end > s) && (g_ascii_isspace(*end) || (*end == '"')))
686 {
687 *end = '\0';
688 --end;
689 }
690
691 return s;
692 }
693
694 #ifdef G_OS_WIN32
695
696 /* Return the home directory with forward slashes instead of backslashes */
697
698 const char*
_gconf_win32_get_home_dir(void)699 _gconf_win32_get_home_dir (void)
700 {
701 static GQuark quark = 0;
702 char *home_copy, *p;
703
704 if (quark != 0)
705 return g_quark_to_string (quark);
706
707 home_copy = g_strdup (g_get_home_dir ());
708
709 /* Replace backslashes with forward slashes */
710 for (p = home_copy; *p; p++)
711 if (*p == '\\')
712 *p = '/';
713
714 quark = g_quark_from_string (home_copy);
715 g_free (home_copy);
716
717 return g_quark_to_string (quark);
718 }
719
720 #endif
721
722 static const gchar *
get_user_source_dir(void)723 get_user_source_dir (void)
724 {
725 static const gchar *user_source = NULL;
726
727 if (user_source == NULL)
728 {
729 gchar *path_new;
730 gchar *path_old;
731
732 path_new = g_build_filename (g_get_user_config_dir (), "gconf", NULL);
733 #ifndef G_OS_WIN32
734 path_old = g_build_filename (g_get_home_dir (), ".gconf", NULL);
735 #else
736 path_old = g_build_filename (_gconf_win32_get_home_dir (), ".gconf", NULL);
737 #endif
738 if ((g_file_test (path_new, G_FILE_TEST_IS_DIR))
739 || (! g_file_test (path_old, G_FILE_TEST_IS_DIR)))
740 {
741 user_source = path_new;
742 g_free (path_old);
743 }
744 else
745 {
746 g_free (path_new);
747 user_source = path_old;
748 }
749 }
750
751 return user_source;
752 }
753
754 static const gchar*
get_variable(const gchar * varname)755 get_variable(const gchar* varname)
756 {
757 /* These first two DO NOT use environment variables, which
758 makes things a bit more "secure" in some sense
759 */
760 if (strcmp(varname, "HOME") == 0)
761 {
762 #ifndef G_OS_WIN32
763 return g_get_home_dir ();
764 #else
765 return _gconf_win32_get_home_dir ();
766 #endif
767 }
768 else if (strcmp(varname, "USERCONFIGDIR") == 0)
769 {
770 return g_get_user_config_dir();
771 }
772 else if (strcmp(varname, "DEFAULTUSERSOURCE") == 0)
773 {
774 return get_user_source_dir();
775 }
776 else if (strcmp(varname, "USER") == 0)
777 {
778 return g_get_user_name();
779 }
780 else if (varname[0] == 'E' &&
781 varname[1] == 'N' &&
782 varname[2] == 'V' &&
783 varname[3] == '_')
784 {
785 /* This is magic: if a variable called ENV_FOO is used,
786 then the environment variable FOO is checked */
787 const gchar* envvar = g_getenv(&varname[4]);
788
789 if (envvar)
790 return envvar;
791 else
792 return "";
793 }
794 else
795 return "";
796 }
797
798 static gchar*
subst_variables(const gchar * src)799 subst_variables(const gchar* src)
800 {
801 const gchar* iter;
802 gchar* retval;
803 guint retval_len;
804 guint pos;
805
806 g_return_val_if_fail(src != NULL, NULL);
807
808 retval_len = strlen(src) + 1;
809 pos = 0;
810
811 retval = g_malloc0(retval_len+3); /* add 3 just to avoid off-by-one
812 segvs - yeah I know it bugs
813 you, but C sucks */
814
815 iter = src;
816
817 while (*iter)
818 {
819 gboolean performed_subst = FALSE;
820
821 if (pos >= retval_len)
822 {
823 retval_len *= 2;
824 retval = g_realloc(retval, retval_len+3); /* add 3 for luck */
825 }
826
827 if (*iter == '$' && *(iter+1) == '(')
828 {
829 const gchar* varstart = iter + 2;
830 const gchar* varend = strchr(varstart, ')');
831
832 if (varend != NULL)
833 {
834 char* varname;
835 const gchar* varval;
836 guint varval_len;
837
838 performed_subst = TRUE;
839
840 varname = g_strndup(varstart, varend - varstart);
841
842 varval = get_variable(varname);
843 g_free(varname);
844
845 varval_len = strlen(varval);
846
847 if ((retval_len - pos) < varval_len)
848 {
849 retval_len = pos + varval_len;
850 retval = g_realloc(retval, retval_len+3);
851 }
852
853 strcpy(&retval[pos], varval);
854 pos += varval_len;
855
856 iter = varend + 1;
857 }
858 }
859
860 if (!performed_subst)
861 {
862 retval[pos] = *iter;
863 ++pos;
864 ++iter;
865 }
866 }
867 retval[pos] = '\0';
868
869 return retval;
870 }
871
872 GSList *
gconf_load_source_path(const gchar * filename,GError ** err)873 gconf_load_source_path(const gchar* filename, GError** err)
874 {
875 FILE* f;
876 GSList *l = NULL;
877 gchar buf[512];
878
879 f = g_fopen(filename, "r");
880
881 if (f == NULL)
882 {
883 if (err)
884 *err = gconf_error_new(GCONF_ERROR_FAILED,
885 _("Couldn't open path file `%s': %s\n"),
886 filename,
887 g_strerror(errno));
888 return NULL;
889 }
890
891 while (fgets(buf, 512, f) != NULL)
892 {
893 gchar* s = buf;
894
895 while (*s && g_ascii_isspace(*s))
896 ++s;
897
898 if (*s == '#')
899 {
900 /* Allow comments, why not */
901 }
902 else if (*s == '\0')
903 {
904 /* Blank line */
905 }
906 else if (strncmp("include", s, 7) == 0)
907 {
908 gchar* unq;
909 GSList* included;
910 gchar *varsubst;
911
912 s += 7;
913 while (g_ascii_isspace(*s))
914 s++;
915 unq = unquote_string(s);
916
917 varsubst = subst_variables (unq);
918 #ifdef G_OS_WIN32
919 {
920 gchar *tem = varsubst;
921 varsubst = _gconf_win32_replace_prefix (varsubst);
922 g_free (tem);
923 }
924 #endif
925 included = gconf_load_source_path (varsubst, NULL);
926 g_free (varsubst);
927
928 if (included != NULL)
929 l = g_slist_concat (l, included);
930 }
931 else
932 {
933 gchar* unq;
934 gchar* varsubst;
935
936 unq = unquote_string(buf);
937 varsubst = subst_variables(unq);
938
939 if (*varsubst != '\0') /* Drop lines with just two quote marks or something */
940 {
941 gconf_log(GCL_DEBUG, _("Adding source `%s'\n"), varsubst);
942 l = g_slist_append (l, varsubst);
943 }
944 else
945 {
946 g_free (varsubst);
947 }
948 }
949 }
950
951 if (ferror(f))
952 {
953 /* This should basically never happen */
954 if (err)
955 *err = gconf_error_new(GCONF_ERROR_FAILED,
956 _("Read error on file `%s': %s\n"),
957 filename,
958 g_strerror(errno));
959 /* don't return, we want to go ahead and return any
960 addresses we already loaded. */
961 }
962
963 fclose(f);
964
965 return l;
966 }
967
968 char *
gconf_address_list_get_persistent_name(GSList * addresses)969 gconf_address_list_get_persistent_name (GSList *addresses)
970 {
971 GSList *tmp;
972 GString *str = NULL;
973
974 if (!addresses)
975 {
976 return g_strdup ("empty");
977 }
978
979 tmp = addresses;
980 while (tmp != NULL)
981 {
982 const char *address = tmp->data;
983
984 if (str == NULL)
985 {
986 str = g_string_new (address);
987 }
988 else
989 {
990 g_string_append_c (str, GCONF_DATABASE_LIST_DELIM);
991 g_string_append (str, address);
992 }
993
994 tmp = tmp->next;
995 }
996
997 return g_string_free (str, FALSE);
998 }
999
1000 GSList *
gconf_persistent_name_get_address_list(const char * persistent_name)1001 gconf_persistent_name_get_address_list (const char *persistent_name)
1002 {
1003 char delim [2] = { GCONF_DATABASE_LIST_DELIM, '\0' };
1004 char **address_vector;
1005
1006 address_vector = g_strsplit (persistent_name, delim, -1);
1007 if (address_vector != NULL)
1008 {
1009 GSList *retval = NULL;
1010 int i;
1011
1012 i = 0;
1013 while (address_vector [i] != NULL)
1014 {
1015 retval = g_slist_append (retval, g_strdup (address_vector [i]));
1016 ++i;
1017 }
1018
1019 g_strfreev (address_vector);
1020
1021 return retval;
1022 }
1023 else
1024 {
1025 return g_slist_append (NULL, g_strdup (persistent_name));
1026 }
1027 }
1028
1029 void
gconf_address_list_free(GSList * addresses)1030 gconf_address_list_free (GSList *addresses)
1031 {
1032 GSList *tmp;
1033
1034 tmp = addresses;
1035 while (tmp != NULL)
1036 {
1037 g_free (tmp->data);
1038 tmp = tmp->next;
1039 }
1040
1041 g_slist_free (addresses);
1042 }
1043
1044 /* This should also support concatting filesystem dirs and keys,
1045 or dir and subdir.
1046 */
1047 gchar*
gconf_concat_dir_and_key(const gchar * dir,const gchar * key)1048 gconf_concat_dir_and_key(const gchar* dir, const gchar* key)
1049 {
1050 guint dirlen;
1051 guint keylen;
1052 gchar* retval;
1053
1054 g_return_val_if_fail(dir != NULL, NULL);
1055 g_return_val_if_fail(key != NULL, NULL);
1056 g_return_val_if_fail(*dir == '/', NULL);
1057
1058 dirlen = strlen(dir);
1059 keylen = strlen(key);
1060
1061 retval = g_malloc0(dirlen+keylen+3); /* auto-null-terminate */
1062
1063 strcpy(retval, dir);
1064
1065 if (dir[dirlen-1] == '/')
1066 {
1067 /* dir ends in slash, strip key slash if needed */
1068 if (*key == '/')
1069 ++key;
1070
1071 strcpy((retval+dirlen), key);
1072 }
1073 else
1074 {
1075 /* Dir doesn't end in slash, add slash if key lacks one. */
1076 gchar* dest = retval + dirlen;
1077
1078 if (*key != '/')
1079 {
1080 *dest = '/';
1081 ++dest;
1082 }
1083
1084 strcpy(dest, key);
1085 }
1086
1087 return retval;
1088 }
1089
1090 gulong
gconf_string_to_gulong(const gchar * str)1091 gconf_string_to_gulong(const gchar* str)
1092 {
1093 gulong retval;
1094 gchar *end;
1095 errno = 0;
1096 retval = strtoul(str, &end, 10);
1097 if (end == str || errno != 0)
1098 retval = 0;
1099
1100 return retval;
1101 }
1102
1103 gboolean
gconf_string_to_double(const gchar * str,gdouble * retloc)1104 gconf_string_to_double(const gchar* str,
1105 gdouble* retloc)
1106 {
1107 char *end;
1108
1109 errno = 0;
1110 *retloc = g_ascii_strtod (str, &end);
1111 if (end == str || errno != 0)
1112 {
1113 *retloc = 0.0;
1114 return FALSE;
1115 }
1116 else
1117 return TRUE;
1118 }
1119
1120 gchar*
gconf_double_to_string(gdouble val)1121 gconf_double_to_string (gdouble val)
1122 {
1123 char str[G_ASCII_DTOSTR_BUF_SIZE];
1124
1125 g_ascii_dtostr (str, G_ASCII_DTOSTR_BUF_SIZE, val);
1126
1127 return g_strdup (str);
1128 }
1129
1130 const gchar*
gconf_current_locale(void)1131 gconf_current_locale(void)
1132 {
1133 #ifdef HAVE_LC_MESSAGES
1134 return setlocale(LC_MESSAGES, NULL);
1135 #else
1136 return setlocale(LC_CTYPE, NULL);
1137 #endif
1138 }
1139
1140 /*
1141 * Log
1142 */
1143
1144 void
gconf_log(GConfLogPriority pri,const gchar * fmt,...)1145 gconf_log(GConfLogPriority pri, const gchar* fmt, ...)
1146 {
1147 va_list args;
1148 GLogLevelFlags loglevel;
1149
1150 if (!gconf_log_debug_messages &&
1151 pri == GCL_DEBUG)
1152 return;
1153
1154 switch (pri)
1155 {
1156 case GCL_EMERG:
1157 case GCL_ALERT:
1158 case GCL_CRIT:
1159 loglevel = G_LOG_LEVEL_ERROR;
1160 break;
1161 case GCL_ERR:
1162 loglevel = G_LOG_LEVEL_CRITICAL;
1163 break;
1164 case GCL_WARNING:
1165 loglevel = G_LOG_LEVEL_WARNING;
1166 break;
1167 case GCL_NOTICE:
1168 loglevel = G_LOG_LEVEL_MESSAGE;
1169 break;
1170 case GCL_INFO:
1171 loglevel = G_LOG_LEVEL_INFO;
1172 break;
1173 case GCL_DEBUG:
1174 loglevel = G_LOG_LEVEL_DEBUG;
1175 break;
1176 default:
1177 g_assert_not_reached();
1178 break;
1179 }
1180
1181 va_start (args, fmt);
1182 g_logv (G_LOG_DOMAIN, loglevel, fmt, args);
1183 va_end (args);
1184 }
1185
1186 /*
1187 * List/pair conversion
1188 */
1189
1190 GConfValue*
gconf_value_list_from_primitive_list(GConfValueType list_type,GSList * list,GError ** err)1191 gconf_value_list_from_primitive_list(GConfValueType list_type, GSList* list,
1192 GError **err)
1193 {
1194 GSList* value_list;
1195 GSList* tmp;
1196
1197 g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL);
1198 g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL);
1199 g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL);
1200
1201 value_list = NULL;
1202
1203 tmp = list;
1204
1205 while (tmp != NULL)
1206 {
1207 GConfValue* val;
1208
1209 val = gconf_value_new(list_type);
1210
1211 switch (list_type)
1212 {
1213 case GCONF_VALUE_INT:
1214 gconf_value_set_int(val, GPOINTER_TO_INT(tmp->data));
1215 break;
1216
1217 case GCONF_VALUE_BOOL:
1218 gconf_value_set_bool(val, GPOINTER_TO_INT(tmp->data));
1219 break;
1220
1221 case GCONF_VALUE_FLOAT:
1222 gconf_value_set_float(val, *((gdouble*)tmp->data));
1223 break;
1224
1225 case GCONF_VALUE_STRING:
1226 if (!g_utf8_validate (tmp->data, -1, NULL))
1227 {
1228 g_set_error (err, GCONF_ERROR,
1229 GCONF_ERROR_FAILED,
1230 _("Text contains invalid UTF-8"));
1231 goto error;
1232 }
1233
1234 gconf_value_set_string(val, tmp->data);
1235 break;
1236
1237 case GCONF_VALUE_SCHEMA:
1238 if (!gconf_schema_validate (tmp->data, err))
1239 goto error;
1240 gconf_value_set_schema(val, tmp->data);
1241 break;
1242
1243 default:
1244 g_assert_not_reached();
1245 break;
1246 }
1247
1248 value_list = g_slist_prepend(value_list, val);
1249
1250 tmp = g_slist_next(tmp);
1251 }
1252
1253 /* Get it in the right order. */
1254 value_list = g_slist_reverse(value_list);
1255
1256 {
1257 GConfValue* value_with_list;
1258
1259 value_with_list = gconf_value_new(GCONF_VALUE_LIST);
1260 gconf_value_set_list_type(value_with_list, list_type);
1261 gconf_value_set_list_nocopy(value_with_list, value_list);
1262
1263 return value_with_list;
1264 }
1265
1266 error:
1267 g_slist_foreach (value_list, (GFunc)gconf_value_free, NULL);
1268 g_slist_free (value_list);
1269 return NULL;
1270 }
1271
1272
1273 static GConfValue*
from_primitive(GConfValueType type,gconstpointer address,GError ** err)1274 from_primitive(GConfValueType type, gconstpointer address,
1275 GError **err)
1276 {
1277 GConfValue* val;
1278
1279 val = gconf_value_new(type);
1280
1281 switch (type)
1282 {
1283 case GCONF_VALUE_INT:
1284 gconf_value_set_int(val, *((const gint*)address));
1285 break;
1286
1287 case GCONF_VALUE_BOOL:
1288 gconf_value_set_bool(val, *((const gboolean*)address));
1289 break;
1290
1291 case GCONF_VALUE_STRING:
1292 if (!g_utf8_validate (*((const gchar**)address), -1, NULL))
1293 {
1294 g_set_error (err, GCONF_ERROR,
1295 GCONF_ERROR_FAILED,
1296 _("Text contains invalid UTF-8"));
1297 gconf_value_free (val);
1298 return NULL;
1299 }
1300
1301 gconf_value_set_string(val, *((const gchar**)address));
1302 break;
1303
1304 case GCONF_VALUE_FLOAT:
1305 gconf_value_set_float(val, *((const gdouble*)address));
1306 break;
1307
1308 case GCONF_VALUE_SCHEMA:
1309 if (!gconf_schema_validate (*((GConfSchema**)address), err))
1310 {
1311 gconf_value_free (val);
1312 return NULL;
1313 }
1314
1315 gconf_value_set_schema(val, *((GConfSchema**)address));
1316 break;
1317
1318 default:
1319 g_assert_not_reached();
1320 break;
1321 }
1322
1323 return val;
1324 }
1325
1326 GConfValue*
gconf_value_pair_from_primitive_pair(GConfValueType car_type,GConfValueType cdr_type,gconstpointer address_of_car,gconstpointer address_of_cdr,GError ** err)1327 gconf_value_pair_from_primitive_pair(GConfValueType car_type,
1328 GConfValueType cdr_type,
1329 gconstpointer address_of_car,
1330 gconstpointer address_of_cdr,
1331 GError **err)
1332 {
1333 GConfValue* pair;
1334 GConfValue* car;
1335 GConfValue* cdr;
1336
1337 g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, NULL);
1338 g_return_val_if_fail(car_type != GCONF_VALUE_LIST, NULL);
1339 g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, NULL);
1340 g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, NULL);
1341 g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, NULL);
1342 g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, NULL);
1343 g_return_val_if_fail(address_of_car != NULL, NULL);
1344 g_return_val_if_fail(address_of_cdr != NULL, NULL);
1345
1346 car = from_primitive(car_type, address_of_car, err);
1347 if (car == NULL)
1348 return NULL;
1349 cdr = from_primitive(cdr_type, address_of_cdr, err);
1350 if (cdr == NULL)
1351 {
1352 gconf_value_free (car);
1353 return NULL;
1354 }
1355
1356 pair = gconf_value_new(GCONF_VALUE_PAIR);
1357 gconf_value_set_car_nocopy(pair, car);
1358 gconf_value_set_cdr_nocopy(pair, cdr);
1359
1360 return pair;
1361 }
1362
1363
1364 GSList*
gconf_value_list_to_primitive_list_destructive(GConfValue * val,GConfValueType list_type,GError ** err)1365 gconf_value_list_to_primitive_list_destructive(GConfValue* val,
1366 GConfValueType list_type,
1367 GError** err)
1368 {
1369 GSList* retval;
1370
1371 g_return_val_if_fail(val != NULL, NULL);
1372 g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL);
1373 g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL);
1374 g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL);
1375 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1376
1377 if (val->type != GCONF_VALUE_LIST)
1378 {
1379 if (err)
1380 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH,
1381 _("Expected list, got %s"),
1382 gconf_value_type_to_string(val->type));
1383 gconf_value_free(val);
1384 return NULL;
1385 }
1386
1387 if (gconf_value_get_list_type(val) != list_type)
1388 {
1389 if (err)
1390 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH,
1391 _("Expected list of %s, got list of %s"),
1392 gconf_value_type_to_string(list_type),
1393 gconf_value_type_to_string(gconf_value_get_list_type (val)));
1394 gconf_value_free(val);
1395 return NULL;
1396 }
1397
1398 g_assert(gconf_value_get_list_type(val) == list_type);
1399
1400 retval = gconf_value_steal_list (val);
1401
1402 gconf_value_free (val);
1403 val = NULL;
1404
1405 {
1406 /* map (typeChange, retval) */
1407 GSList* tmp;
1408
1409 tmp = retval;
1410
1411 while (tmp != NULL)
1412 {
1413 GConfValue* elem = tmp->data;
1414
1415 g_assert(elem != NULL);
1416 g_assert(elem->type == list_type);
1417
1418 switch (list_type)
1419 {
1420 case GCONF_VALUE_INT:
1421 tmp->data = GINT_TO_POINTER(gconf_value_get_int(elem));
1422 break;
1423
1424 case GCONF_VALUE_BOOL:
1425 tmp->data = GINT_TO_POINTER(gconf_value_get_bool(elem));
1426 break;
1427
1428 case GCONF_VALUE_FLOAT:
1429 {
1430 gdouble* d = g_new(gdouble, 1);
1431 *d = gconf_value_get_float(elem);
1432 tmp->data = d;
1433 }
1434 break;
1435
1436 case GCONF_VALUE_STRING:
1437 tmp->data = gconf_value_steal_string (elem);
1438 break;
1439
1440 case GCONF_VALUE_SCHEMA:
1441 tmp->data = gconf_value_steal_schema (elem);
1442 break;
1443
1444 default:
1445 g_assert_not_reached();
1446 break;
1447 }
1448
1449 /* Clean up the value */
1450 gconf_value_free(elem);
1451
1452 tmp = g_slist_next(tmp);
1453 }
1454 } /* list conversion block */
1455
1456 return retval;
1457 }
1458
1459
1460 static void
primitive_value(gpointer retloc,GConfValue * val)1461 primitive_value(gpointer retloc, GConfValue* val)
1462 {
1463 switch (val->type)
1464 {
1465 case GCONF_VALUE_INT:
1466 *((gint*)retloc) = gconf_value_get_int(val);
1467 break;
1468
1469 case GCONF_VALUE_FLOAT:
1470 *((gdouble*)retloc) = gconf_value_get_float(val);
1471 break;
1472
1473 case GCONF_VALUE_STRING:
1474 {
1475 *((gchar**)retloc) = gconf_value_steal_string (val);
1476 }
1477 break;
1478
1479 case GCONF_VALUE_BOOL:
1480 *((gboolean*)retloc) = gconf_value_get_bool(val);
1481 break;
1482
1483 case GCONF_VALUE_SCHEMA:
1484 *((GConfSchema**)retloc) = gconf_value_steal_schema(val);
1485 break;
1486
1487 default:
1488 g_assert_not_reached();
1489 break;
1490 }
1491 }
1492
1493 gboolean
gconf_value_pair_to_primitive_pair_destructive(GConfValue * val,GConfValueType car_type,GConfValueType cdr_type,gpointer car_retloc,gpointer cdr_retloc,GError ** err)1494 gconf_value_pair_to_primitive_pair_destructive(GConfValue* val,
1495 GConfValueType car_type,
1496 GConfValueType cdr_type,
1497 gpointer car_retloc,
1498 gpointer cdr_retloc,
1499 GError** err)
1500 {
1501 GConfValue* car;
1502 GConfValue* cdr;
1503
1504 g_return_val_if_fail(val != NULL, FALSE);
1505 g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
1506 g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
1507 g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
1508 g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
1509 g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
1510 g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
1511 g_return_val_if_fail(car_retloc != NULL, FALSE);
1512 g_return_val_if_fail(cdr_retloc != NULL, FALSE);
1513 g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
1514
1515 if (val->type != GCONF_VALUE_PAIR)
1516 {
1517 if (err)
1518 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH,
1519 _("Expected pair, got %s"),
1520 gconf_value_type_to_string(val->type));
1521 gconf_value_free(val);
1522 return FALSE;
1523 }
1524
1525 car = gconf_value_get_car(val);
1526 cdr = gconf_value_get_cdr(val);
1527
1528 if (car == NULL ||
1529 cdr == NULL)
1530 {
1531 if (err)
1532 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH,
1533 _("Expected (%s,%s) pair, got a pair with one or both values missing"),
1534 gconf_value_type_to_string(car_type),
1535 gconf_value_type_to_string(cdr_type));
1536
1537 gconf_value_free(val);
1538 return FALSE;
1539 }
1540
1541 g_assert(car != NULL);
1542 g_assert(cdr != NULL);
1543
1544 if (car->type != car_type ||
1545 cdr->type != cdr_type)
1546 {
1547 if (err)
1548 *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH,
1549 _("Expected pair of type (%s,%s) got type (%s,%s)"),
1550 gconf_value_type_to_string(car_type),
1551 gconf_value_type_to_string(cdr_type),
1552 gconf_value_type_to_string(car->type),
1553 gconf_value_type_to_string(cdr->type));
1554 gconf_value_free(val);
1555 return FALSE;
1556 }
1557
1558 primitive_value(car_retloc, car);
1559 primitive_value(cdr_retloc, cdr);
1560
1561 gconf_value_free(val);
1562
1563 return TRUE;
1564 }
1565
1566
1567
1568 /*
1569 * Encode/decode
1570 */
1571
1572 gchar*
gconf_quote_string(const gchar * src)1573 gconf_quote_string (const gchar* src)
1574 {
1575 gchar* dest;
1576 const gchar* s;
1577 gchar* d;
1578
1579 g_return_val_if_fail(src != NULL, NULL);
1580
1581 /* waste memory! woo-hoo! */
1582 dest = g_malloc0(strlen(src)*2+4);
1583
1584 d = dest;
1585
1586 *d = '"';
1587 ++d;
1588
1589 s = src;
1590 while (*s)
1591 {
1592 switch (*s)
1593 {
1594 case '"':
1595 {
1596 *d = '\\';
1597 ++d;
1598 *d = '"';
1599 ++d;
1600 }
1601 break;
1602
1603 case '\\':
1604 {
1605 *d = '\\';
1606 ++d;
1607 *d = '\\';
1608 ++d;
1609 }
1610 break;
1611
1612 default:
1613 {
1614 *d = *s;
1615 ++d;
1616 }
1617 break;
1618 }
1619 ++s;
1620 }
1621
1622 /* End with quote mark and NULL */
1623 *d = '"';
1624 ++d;
1625 *d = '\0';
1626
1627 return dest;
1628 }
1629
1630 gchar*
gconf_unquote_string(const gchar * str,const gchar ** end,GError ** err)1631 gconf_unquote_string (const gchar* str, const gchar** end, GError** err)
1632 {
1633 gchar* unq;
1634 gchar* unq_end = NULL;
1635
1636 g_return_val_if_fail(end != NULL, NULL);
1637 g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1638 g_return_val_if_fail(str != NULL, NULL);
1639
1640 unq = g_strdup(str);
1641
1642 gconf_unquote_string_inplace(unq, &unq_end, err);
1643
1644 *end = (str + (unq_end - unq));
1645
1646 return unq;
1647 }
1648
1649 void
gconf_unquote_string_inplace(gchar * str,gchar ** end,GError ** err)1650 gconf_unquote_string_inplace (gchar* str, gchar** end, GError** err)
1651 {
1652 gchar* dest;
1653 gchar* s;
1654
1655 g_return_if_fail(end != NULL);
1656 g_return_if_fail(err == NULL || *err == NULL);
1657 g_return_if_fail(str != NULL);
1658
1659 dest = s = str;
1660
1661 if (*s != '"')
1662 {
1663 if (err)
1664 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
1665 _("Quoted string doesn't begin with a quotation mark"));
1666 *end = str;
1667 return;
1668 }
1669
1670 /* Skip the initial quote mark */
1671 ++s;
1672
1673 while (*s)
1674 {
1675 g_assert(s > dest); /* loop invariant */
1676
1677 switch (*s)
1678 {
1679 case '"':
1680 /* End of the string, return now */
1681 *dest = '\0';
1682 ++s;
1683 *end = s;
1684 return;
1685
1686 case '\\':
1687 /* Possible escaped quote or \ */
1688 ++s;
1689 if (*s == '"')
1690 {
1691 *dest = *s;
1692 ++s;
1693 ++dest;
1694 }
1695 else if (*s == '\\')
1696 {
1697 *dest = *s;
1698 ++s;
1699 ++dest;
1700 }
1701 else
1702 {
1703 /* not an escaped char */
1704 *dest = '\\';
1705 ++dest;
1706 /* ++s already done. */
1707 }
1708 break;
1709
1710 default:
1711 *dest = *s;
1712 ++dest;
1713 ++s;
1714 break;
1715 }
1716
1717 g_assert(s > dest); /* loop invariant */
1718 }
1719
1720 /* If we reach here this means the close quote was never encountered */
1721
1722 *dest = '\0';
1723
1724 if (err)
1725 *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR,
1726 _("Quoted string doesn't end with a quotation mark"));
1727 *end = s;
1728 return;
1729 }
1730
1731 /* The encoding format
1732
1733 The first byte of the encoded string is the type of the value:
1734
1735 i int
1736 b bool
1737 f float
1738 s string
1739 c schema
1740 p pair
1741 l list
1742 v invalid
1743
1744 For int, the rest of the encoded value is the integer to be parsed with atoi()
1745 For bool, the rest is 't' or 'f'
1746 For float, the rest is a float to parse with g_strtod()
1747 For string, the rest is the string (not quoted)
1748 For schema, the encoding is complicated; see below.
1749 For pair, the rest is two primitive encodings (ibcfs), quoted, separated by a comma,
1750 car before cdr
1751 For list, first character is type, the rest is primitive encodings, quoted,
1752 separated by commas
1753
1754 Schema:
1755
1756 After the 'c' indicating schema, the second character is a byte indicating
1757 the type the schema expects. Then a comma, and the quoted locale, or "" for none.
1758 comma, and quoted short description; comma, quoted long description; comma, default
1759 value in the encoded format given above, quoted.
1760 */
1761
type_byte(GConfValueType type)1762 static gchar type_byte(GConfValueType type)
1763 {
1764 switch (type)
1765 {
1766 case GCONF_VALUE_INT:
1767 return 'i';
1768
1769 case GCONF_VALUE_BOOL:
1770 return 'b';
1771
1772 case GCONF_VALUE_FLOAT:
1773 return 'f';
1774
1775 case GCONF_VALUE_STRING:
1776 return 's';
1777
1778 case GCONF_VALUE_SCHEMA:
1779 return 'c';
1780
1781 case GCONF_VALUE_LIST:
1782 return 'l';
1783
1784 case GCONF_VALUE_PAIR:
1785 return 'p';
1786
1787 case GCONF_VALUE_INVALID:
1788 return 'v';
1789
1790 default:
1791 g_assert_not_reached();
1792 return '\0';
1793 }
1794 }
1795
1796 static GConfValueType
byte_type(gchar byte)1797 byte_type(gchar byte)
1798 {
1799 switch (byte)
1800 {
1801 case 'i':
1802 return GCONF_VALUE_INT;
1803
1804 case 'b':
1805 return GCONF_VALUE_BOOL;
1806
1807 case 's':
1808 return GCONF_VALUE_STRING;
1809
1810 case 'c':
1811 return GCONF_VALUE_SCHEMA;
1812
1813 case 'f':
1814 return GCONF_VALUE_FLOAT;
1815
1816 case 'l':
1817 return GCONF_VALUE_LIST;
1818
1819 case 'p':
1820 return GCONF_VALUE_PAIR;
1821
1822 case 'v':
1823 return GCONF_VALUE_INVALID;
1824
1825 default:
1826 return GCONF_VALUE_INVALID;
1827 }
1828 }
1829
1830 GConfValue*
gconf_value_decode(const gchar * encoded)1831 gconf_value_decode (const gchar* encoded)
1832 {
1833 GConfValueType type;
1834 GConfValue* val;
1835 const gchar* s;
1836
1837 type = byte_type(*encoded);
1838
1839 if (type == GCONF_VALUE_INVALID)
1840 return NULL;
1841
1842 if (!g_utf8_validate (encoded, -1, NULL))
1843 {
1844 gconf_log (GCL_ERR, _("Encoded value is not valid UTF-8"));
1845 return NULL;
1846 }
1847
1848 val = gconf_value_new(type);
1849
1850 s = encoded + 1;
1851
1852 switch (val->type)
1853 {
1854 case GCONF_VALUE_INT:
1855 gconf_value_set_int(val, atoi(s));
1856 break;
1857
1858 case GCONF_VALUE_BOOL:
1859 gconf_value_set_bool(val, *s == 't' ? TRUE : FALSE);
1860 break;
1861
1862 case GCONF_VALUE_FLOAT:
1863 {
1864 double d;
1865 gchar* endptr = NULL;
1866
1867 d = g_strtod(s, &endptr);
1868 if (endptr == s)
1869 g_warning("Failure converting string to double in %s", G_STRFUNC);
1870 gconf_value_set_float(val, d);
1871 }
1872 break;
1873
1874 case GCONF_VALUE_STRING:
1875 {
1876 gconf_value_set_string(val, s);
1877 }
1878 break;
1879
1880 case GCONF_VALUE_SCHEMA:
1881 {
1882 GConfSchema* sc = gconf_schema_new();
1883 const gchar* end = NULL;
1884 gchar* unquoted;
1885
1886 gconf_value_set_schema_nocopy(val, sc);
1887
1888 gconf_schema_set_type(sc, byte_type(*s));
1889 ++s;
1890 gconf_schema_set_list_type(sc, byte_type(*s));
1891 ++s;
1892 gconf_schema_set_car_type(sc, byte_type(*s));
1893 ++s;
1894 gconf_schema_set_cdr_type(sc, byte_type(*s));
1895 ++s;
1896
1897 if (*s != ',')
1898 g_warning("no comma after types in schema");
1899
1900 ++s;
1901
1902 /* locale */
1903 unquoted = gconf_unquote_string(s, &end, NULL);
1904
1905 gconf_schema_set_locale(sc, unquoted);
1906
1907 g_free(unquoted);
1908
1909 if (*end != ',')
1910 g_warning("no comma after locale in schema");
1911
1912 ++end;
1913 s = end;
1914
1915 /* short */
1916 unquoted = gconf_unquote_string(s, &end, NULL);
1917
1918 gconf_schema_set_short_desc(sc, unquoted);
1919
1920 g_free(unquoted);
1921
1922 if (*end != ',')
1923 g_warning("no comma after short desc in schema");
1924
1925 ++end;
1926 s = end;
1927
1928 /* long */
1929 unquoted = gconf_unquote_string(s, &end, NULL);
1930
1931 gconf_schema_set_long_desc(sc, unquoted);
1932
1933 g_free(unquoted);
1934
1935 if (*end != ',')
1936 g_warning("no comma after long desc in schema");
1937
1938 ++end;
1939 s = end;
1940
1941 /* default value */
1942 unquoted = gconf_unquote_string(s, &end, NULL);
1943
1944 gconf_schema_set_default_value_nocopy(sc, gconf_value_decode(unquoted));
1945
1946 g_free(unquoted);
1947
1948 if (*end != '\0')
1949 g_warning("trailing junk after encoded schema");
1950 }
1951 break;
1952
1953 case GCONF_VALUE_LIST:
1954 {
1955 GSList* value_list = NULL;
1956
1957 gconf_value_set_list_type(val, byte_type(*s));
1958 ++s;
1959
1960 while (*s)
1961 {
1962 gchar* unquoted;
1963 const gchar* end;
1964
1965 GConfValue* elem;
1966
1967 unquoted = gconf_unquote_string(s, &end, NULL);
1968
1969 elem = gconf_value_decode(unquoted);
1970
1971 g_free(unquoted);
1972
1973 if (elem)
1974 value_list = g_slist_prepend(value_list, elem);
1975
1976 s = end;
1977 if (*s == ',')
1978 ++s;
1979 else if (*s != '\0')
1980 {
1981 g_warning("weird character in encoded list");
1982 break; /* error */
1983 }
1984 }
1985
1986 value_list = g_slist_reverse(value_list);
1987
1988 gconf_value_set_list_nocopy(val, value_list);
1989 }
1990 break;
1991
1992 case GCONF_VALUE_PAIR:
1993 {
1994 gchar* unquoted;
1995 const gchar* end;
1996
1997 GConfValue* car;
1998 GConfValue* cdr;
1999
2000 unquoted = gconf_unquote_string(s, &end, NULL);
2001
2002 car = gconf_value_decode(unquoted);
2003
2004 g_free(unquoted);
2005
2006 s = end;
2007 if (*s == ',')
2008 ++s;
2009 else
2010 {
2011 g_warning("weird character in encoded pair");
2012 }
2013
2014 unquoted = gconf_unquote_string(s, &end, NULL);
2015
2016 cdr = gconf_value_decode(unquoted);
2017 g_free(unquoted);
2018
2019
2020 gconf_value_set_car_nocopy(val, car);
2021 gconf_value_set_cdr_nocopy(val, cdr);
2022 }
2023 break;
2024
2025 default:
2026 g_assert_not_reached();
2027 break;
2028 }
2029
2030 return val;
2031 }
2032
2033 gchar*
gconf_value_encode(GConfValue * val)2034 gconf_value_encode (GConfValue* val)
2035 {
2036 gchar* retval = NULL;
2037
2038 g_return_val_if_fail(val != NULL, NULL);
2039
2040 switch (val->type)
2041 {
2042 case GCONF_VALUE_INT:
2043 retval = g_strdup_printf("i%d", gconf_value_get_int(val));
2044 break;
2045
2046 case GCONF_VALUE_BOOL:
2047 retval = g_strdup_printf("b%c", gconf_value_get_bool(val) ? 't' : 'f');
2048 break;
2049
2050 case GCONF_VALUE_FLOAT:
2051 retval = g_strdup_printf("f%g", gconf_value_get_float(val));
2052 break;
2053
2054 case GCONF_VALUE_STRING:
2055 retval = g_strdup_printf("s%s", gconf_value_get_string(val));
2056 break;
2057
2058 case GCONF_VALUE_SCHEMA:
2059 {
2060 gchar* tmp;
2061 gchar* quoted;
2062 gchar* encoded;
2063 GConfSchema* sc;
2064
2065 sc = gconf_value_get_schema(val);
2066
2067 tmp = g_strdup_printf("c%c%c%c%c,",
2068 type_byte(gconf_schema_get_type(sc)),
2069 type_byte(gconf_schema_get_list_type(sc)),
2070 type_byte(gconf_schema_get_car_type(sc)),
2071 type_byte(gconf_schema_get_cdr_type(sc)));
2072
2073 quoted = gconf_quote_string(gconf_schema_get_locale(sc) ?
2074 gconf_schema_get_locale(sc) : "");
2075 retval = g_strconcat(tmp, quoted, ",", NULL);
2076
2077 g_free(tmp);
2078 g_free(quoted);
2079
2080 tmp = retval;
2081 quoted = gconf_quote_string(gconf_schema_get_short_desc(sc) ?
2082 gconf_schema_get_short_desc(sc) : "");
2083
2084 retval = g_strconcat(tmp, quoted, ",", NULL);
2085
2086 g_free(tmp);
2087 g_free(quoted);
2088
2089
2090 tmp = retval;
2091 quoted = gconf_quote_string(gconf_schema_get_long_desc(sc) ?
2092 gconf_schema_get_long_desc(sc) : "");
2093
2094 retval = g_strconcat(tmp, quoted, ",", NULL);
2095
2096 g_free(tmp);
2097 g_free(quoted);
2098
2099
2100 if (gconf_schema_get_default_value(sc) != NULL)
2101 encoded = gconf_value_encode(gconf_schema_get_default_value(sc));
2102 else
2103 encoded = g_strdup("");
2104
2105 tmp = retval;
2106
2107 quoted = gconf_quote_string(encoded);
2108
2109 retval = g_strconcat(tmp, quoted, NULL);
2110
2111 g_free(tmp);
2112 g_free(quoted);
2113 g_free(encoded);
2114 }
2115 break;
2116
2117 case GCONF_VALUE_LIST:
2118 {
2119 GSList* tmp;
2120
2121 retval = g_strdup_printf("l%c", type_byte(gconf_value_get_list_type(val)));
2122
2123 tmp = gconf_value_get_list(val);
2124
2125 while (tmp != NULL)
2126 {
2127 GConfValue* elem = tmp->data;
2128 gchar* encoded;
2129 gchar* quoted;
2130
2131 g_assert(elem != NULL);
2132
2133 encoded = gconf_value_encode(elem);
2134
2135 quoted = gconf_quote_string(encoded);
2136
2137 g_free(encoded);
2138
2139 {
2140 gchar* free_me;
2141 free_me = retval;
2142
2143 retval = g_strconcat(retval, ",", quoted, NULL);
2144
2145 g_free(quoted);
2146 g_free(free_me);
2147 }
2148
2149 tmp = g_slist_next(tmp);
2150 }
2151 }
2152 break;
2153
2154 case GCONF_VALUE_PAIR:
2155 {
2156 gchar* car_encoded;
2157 gchar* cdr_encoded;
2158 gchar* car_quoted;
2159 gchar* cdr_quoted;
2160
2161 car_encoded = gconf_value_encode(gconf_value_get_car(val));
2162 cdr_encoded = gconf_value_encode(gconf_value_get_cdr(val));
2163
2164 car_quoted = gconf_quote_string(car_encoded);
2165 cdr_quoted = gconf_quote_string(cdr_encoded);
2166
2167 retval = g_strconcat("p", car_quoted, ",", cdr_quoted, NULL);
2168
2169 g_free(car_encoded);
2170 g_free(cdr_encoded);
2171 g_free(car_quoted);
2172 g_free(cdr_quoted);
2173 }
2174 break;
2175
2176 default:
2177 g_assert_not_reached();
2178 break;
2179
2180 }
2181
2182 return retval;
2183 }
2184
2185 #ifdef HAVE_CORBA
2186
2187 /*
2188 * Locks
2189 */
2190
2191 /*
2192 * Locks works as follows. We have a lock directory to hold the locking
2193 * mess, and we have an IOR file inside the lock directory with the
2194 * gconfd IOR, and we have an fcntl() lock on the IOR file. The IOR
2195 * file is created atomically using a temporary file, then link()
2196 */
2197
2198 struct _GConfLock {
2199 gchar *lock_directory;
2200 gchar *iorfile;
2201 int lock_fd;
2202 };
2203
2204 static void
gconf_lock_destroy(GConfLock * lock)2205 gconf_lock_destroy (GConfLock* lock)
2206 {
2207 if (lock->lock_fd >= 0)
2208 close (lock->lock_fd);
2209 g_free (lock->iorfile);
2210 g_free (lock->lock_directory);
2211 g_free (lock);
2212 }
2213
2214 #ifndef G_OS_WIN32
2215
2216 static void
set_close_on_exec(int fd)2217 set_close_on_exec (int fd)
2218 {
2219 #if defined (F_GETFD) && defined (FD_CLOEXEC)
2220 int val;
2221
2222 val = fcntl (fd, F_GETFD, 0);
2223 if (val < 0)
2224 {
2225 gconf_log (GCL_DEBUG, "couldn't F_GETFD: %s\n", g_strerror (errno));
2226 return;
2227 }
2228
2229 val |= FD_CLOEXEC;
2230
2231 if (fcntl (fd, F_SETFD, val) < 0)
2232 gconf_log (GCL_DEBUG, "couldn't F_SETFD: %s\n", g_strerror (errno));
2233 #endif
2234 }
2235
2236 #endif
2237
2238 #ifdef F_SETLK
2239 /* Your basic Stevens cut-and-paste */
2240 static int
lock_reg(int fd,int cmd,int type,off_t offset,int whence,off_t len)2241 lock_reg (int fd, int cmd, int type, off_t offset, int whence, off_t len)
2242 {
2243 struct flock lock;
2244
2245 lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */
2246 lock.l_start = offset; /* byte offset relative to whence */
2247 lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
2248 lock.l_len = len; /* #bytes, 0 for eof */
2249
2250 return fcntl (fd, cmd, &lock);
2251 }
2252 #endif
2253
2254 #ifdef F_SETLK
2255 #define lock_entire_file(fd) \
2256 lock_reg ((fd), F_SETLK, F_WRLCK, 0, SEEK_SET, 0)
2257 #define unlock_entire_file(fd) \
2258 lock_reg ((fd), F_SETLK, F_UNLCK, 0, SEEK_SET, 0)
2259 #elif defined (G_OS_WIN32)
2260 /* We don't use these macros */
2261 #else
2262 #warning Please implement proper locking
2263 #define lock_entire_file(fd) 0
2264 #define unlock_entire_file(fd) 0
2265 #endif
2266
2267 static gboolean
file_locked_by_someone_else(int fd)2268 file_locked_by_someone_else (int fd)
2269 {
2270 #ifdef F_SETLK
2271 struct flock lock;
2272
2273 lock.l_type = F_WRLCK;
2274 lock.l_start = 0;
2275 lock.l_whence = SEEK_SET;
2276 lock.l_len = 0;
2277
2278 if (fcntl (fd, F_GETLK, &lock) < 0)
2279 return TRUE; /* pretend it's locked */
2280
2281 if (lock.l_type == F_UNLCK)
2282 return FALSE; /* we have the lock */
2283 else
2284 return TRUE; /* someone else has it */
2285 #else
2286 return FALSE;
2287 #endif
2288 }
2289
2290 #ifndef G_OS_WIN32
2291
2292 static char*
unique_filename(const char * directory)2293 unique_filename (const char *directory)
2294 {
2295 char *guid;
2296 char *uniquefile;
2297
2298 guid = gconf_unique_key ();
2299 uniquefile = g_strconcat (directory, "/", guid, NULL);
2300 g_free (guid);
2301
2302 return uniquefile;
2303 }
2304
2305 #endif
2306
2307 static int
create_new_locked_file(const gchar * directory,const gchar * filename,GError ** err)2308 create_new_locked_file (const gchar *directory,
2309 const gchar *filename,
2310 GError **err)
2311 {
2312 int fd;
2313 gboolean got_lock = FALSE;
2314
2315 #ifndef G_OS_WIN32
2316
2317 char *uniquefile = unique_filename (directory);
2318
2319 fd = open (uniquefile, O_WRONLY | O_CREAT, 0700);
2320
2321 /* Lock our temporary file, lock hopefully applies to the
2322 * inode and so also counts once we link it to the new name
2323 */
2324 if (lock_entire_file (fd) < 0)
2325 {
2326 g_set_error (err,
2327 GCONF_ERROR,
2328 GCONF_ERROR_LOCK_FAILED,
2329 _("Could not lock temporary file '%s': %s"),
2330 uniquefile, g_strerror (errno));
2331 goto out;
2332 }
2333
2334 /* Create lockfile as a link to unique file */
2335 if (link (uniquefile, filename) == 0)
2336 {
2337 /* filename didn't exist before, and open succeeded, and we have the lock */
2338 got_lock = TRUE;
2339 goto out;
2340 }
2341 else
2342 {
2343 /* see if the link really succeeded */
2344 struct stat sb;
2345 if (stat (uniquefile, &sb) == 0 &&
2346 sb.st_nlink == 2)
2347 {
2348 got_lock = TRUE;
2349 goto out;
2350 }
2351 else
2352 {
2353 g_set_error (err,
2354 GCONF_ERROR,
2355 GCONF_ERROR_LOCK_FAILED,
2356 _("Could not create file '%s', probably because it already exists"),
2357 filename);
2358 goto out;
2359 }
2360 }
2361
2362 out:
2363 if (got_lock)
2364 set_close_on_exec (fd);
2365
2366 unlink (uniquefile);
2367 g_free (uniquefile);
2368
2369 #else
2370
2371 if (G_WIN32_HAVE_WIDECHAR_API ())
2372 {
2373 wchar_t *wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
2374 fd = _wsopen (wfilename, O_WRONLY|O_CREAT|O_EXCL, SH_DENYWR, 0700);
2375 g_free (wfilename);
2376 }
2377 else
2378 {
2379 char *cpfilename = g_locale_from_utf8 (filename, -1, NULL, NULL, NULL);
2380 fd = _sopen (cpfilename, O_WRONLY|O_CREAT|O_EXCL, SH_DENYWR, 0700);
2381 g_free (cpfilename);
2382 }
2383
2384 got_lock = (fd >= 0);
2385
2386 #endif
2387
2388 if (!got_lock)
2389 {
2390 if (fd >= 0)
2391 close (fd);
2392 fd = -1;
2393 }
2394
2395 return fd;
2396 }
2397
2398 static int
open_empty_locked_file(const gchar * directory,const gchar * filename,GError ** err)2399 open_empty_locked_file (const gchar *directory,
2400 const gchar *filename,
2401 GError **err)
2402 {
2403 int fd;
2404
2405 fd = create_new_locked_file (directory, filename, NULL);
2406
2407 if (fd >= 0)
2408 return fd;
2409
2410 /* We failed to create the file, most likely because it already
2411 * existed; try to get the lock on the existing file, and if we can
2412 * get that lock, delete it, then start over.
2413 */
2414
2415 #ifndef G_OS_WIN32
2416
2417 fd = open (filename, O_RDWR, 0700);
2418 if (fd < 0)
2419 {
2420 /* File has gone away? */
2421 g_set_error (err,
2422 GCONF_ERROR,
2423 GCONF_ERROR_LOCK_FAILED,
2424 _("Failed to create or open '%s'"),
2425 filename);
2426 return -1;
2427 }
2428
2429 if (lock_entire_file (fd) < 0)
2430 {
2431 g_set_error (err,
2432 GCONF_ERROR,
2433 GCONF_ERROR_LOCK_FAILED,
2434 _("Failed to lock '%s': probably another process has the lock, or your operating system has NFS file locking misconfigured (%s)"),
2435 filename, g_strerror (errno));
2436 close (fd);
2437 return -1;
2438 }
2439
2440 /* We have the lock on filename, so delete it */
2441 /* FIXME this leaves .nfs32423432 cruft */
2442 unlink (filename);
2443 close (fd);
2444 fd = -1;
2445
2446 #else
2447 /* Unlinking open files fail on Win32 */
2448
2449 if (g_remove (filename) == -1)
2450 {
2451 g_set_error (err,
2452 GCONF_ERROR,
2453 GCONF_ERROR_LOCK_FAILED,
2454 _("Failed to remove '%s': %s"),
2455 filename, g_strerror (errno));
2456 return -1;
2457 }
2458 #endif
2459
2460 /* Now retry creating our file */
2461 fd = create_new_locked_file (directory, filename, err);
2462
2463 return fd;
2464 }
2465
2466 static char *
get_ior(gboolean start_if_not_found,GString * failure_log)2467 get_ior (gboolean start_if_not_found,
2468 GString *failure_log)
2469 {
2470 GDBusConnection *connection;
2471 GVariant *value;
2472 char *ior;
2473 GError *error = NULL;
2474
2475 /* if the bus isn't running and we don't want to start gconfd then
2476 * we don't want to autolaunch the bus either, so bail early.
2477 */
2478 if ((g_getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL && g_getenv ("DBUS_LAUNCHD_SESSION_BUS_SOCKET") == NULL ) &&
2479 (!start_if_not_found || g_getenv ("DISPLAY") == NULL)) {
2480 if (failure_log)
2481 g_string_append_printf (failure_log,
2482 _("Not running within active session"));
2483 return NULL;
2484 }
2485
2486 g_type_init ();
2487
2488 connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
2489 if (connection == NULL) {
2490 if (failure_log)
2491 g_string_append_printf (failure_log,
2492 _("Failed to get connection to session: %s"),
2493 error->message);
2494 g_error_free (error);
2495 return NULL;
2496 }
2497
2498 value = g_dbus_connection_call_sync (connection,
2499 "org.gnome.GConf",
2500 "/org/gnome/GConf",
2501 "org.gnome.GConf",
2502 "GetIOR",
2503 g_variant_new ("()"),
2504 G_VARIANT_TYPE ("(s)"),
2505 start_if_not_found ? G_DBUS_CALL_FLAGS_NONE
2506 : G_DBUS_CALL_FLAGS_NO_AUTO_START,
2507 -1,
2508 NULL,
2509 &error);
2510 g_object_unref (connection);
2511
2512 if (value == NULL) {
2513 if (failure_log)
2514 g_string_append_printf (failure_log,
2515 _("GetIOR failed: %s"),
2516 error->message);
2517
2518 g_error_free (error);
2519 return NULL;
2520 }
2521
2522 g_variant_get (value, "(s)", &ior, NULL);
2523 g_variant_unref (value);
2524
2525 return ior;
2526 }
2527
2528 static ConfigServer
gconf_get_server(gboolean start_if_not_found,GString * failure_log)2529 gconf_get_server (gboolean start_if_not_found,
2530 GString *failure_log)
2531 {
2532 ConfigServer server;
2533 char *ior;
2534 CORBA_ORB orb;
2535 CORBA_Environment ev;
2536
2537 ior = get_ior (start_if_not_found, failure_log);
2538
2539 if (ior == NULL)
2540 {
2541 return CORBA_OBJECT_NIL;
2542 }
2543
2544 CORBA_exception_init (&ev);
2545 orb = gconf_orb_get ();
2546
2547 if (orb == NULL)
2548 {
2549 if (failure_log)
2550 {
2551 g_string_append_printf (failure_log,
2552 _("couldn't contact ORB to resolve existing gconfd object reference"));
2553 g_free (ior);
2554 }
2555 return CORBA_OBJECT_NIL;
2556 }
2557
2558 server = CORBA_ORB_string_to_object (orb, (char*) ior, &ev);
2559 CORBA_exception_free (&ev);
2560
2561 if (server == CORBA_OBJECT_NIL &&
2562 failure_log)
2563 g_string_append_printf (failure_log,
2564 _("Failed to convert IOR '%s' to an object reference"),
2565 ior);
2566
2567 g_free (ior);
2568
2569 return server;
2570 }
2571
2572 static GConfLock *
gconf_get_lock_or_current_holder(const gchar * lock_directory,ConfigServer * current_server,GError ** err)2573 gconf_get_lock_or_current_holder (const gchar *lock_directory,
2574 ConfigServer *current_server,
2575 GError **err)
2576 {
2577 GConfLock* lock;
2578
2579 g_return_val_if_fail(lock_directory != NULL, NULL);
2580
2581 if (current_server)
2582 *current_server = CORBA_OBJECT_NIL;
2583
2584 if (g_mkdir (lock_directory, 0700) < 0 &&
2585 errno != EEXIST)
2586 {
2587 int errsv = errno;
2588
2589 gconf_set_error (err,
2590 GCONF_ERROR_LOCK_FAILED,
2591 _("couldn't create directory `%s': %s"),
2592 lock_directory, g_strerror (errsv));
2593
2594 return NULL;
2595 }
2596
2597 lock = g_new0 (GConfLock, 1);
2598
2599 lock->lock_directory = g_strdup (lock_directory);
2600
2601 lock->iorfile = g_strconcat (lock->lock_directory, "/ior", NULL);
2602
2603 /* Check the current IOR file and ping its daemon */
2604
2605 lock->lock_fd = open_empty_locked_file (lock->lock_directory,
2606 lock->iorfile,
2607 err);
2608
2609 if (lock->lock_fd < 0)
2610 {
2611 /* We didn't get the lock. Read the old server, and provide
2612 * it to the caller. Error is already set.
2613 */
2614 if (current_server)
2615 *current_server = gconf_get_server (FALSE, NULL);
2616
2617 gconf_lock_destroy (lock);
2618
2619 return NULL;
2620 }
2621 else
2622 {
2623 /* Write IOR to lockfile */
2624 const gchar* ior;
2625 int retval;
2626 gchar* s;
2627
2628 s = g_strdup_printf ("%u:", (guint) getpid ());
2629
2630 retval = write (lock->lock_fd, s, strlen (s));
2631
2632 g_free (s);
2633
2634 if (retval >= 0)
2635 {
2636 ior = gconf_get_daemon_ior();
2637
2638 if (ior == NULL)
2639 retval = write (lock->lock_fd, "none", 4);
2640 else
2641 retval = write (lock->lock_fd, ior, strlen (ior));
2642 }
2643
2644 if (retval < 0)
2645 {
2646 gconf_set_error (err,
2647 GCONF_ERROR_LOCK_FAILED,
2648 _("Can't write to file `%s': %s"),
2649 lock->iorfile, g_strerror (errno));
2650
2651 g_unlink (lock->iorfile);
2652 gconf_lock_destroy (lock);
2653
2654 return NULL;
2655 }
2656 }
2657
2658 return lock;
2659 }
2660
2661 GConfLock*
gconf_get_lock(const gchar * lock_directory,GError ** err)2662 gconf_get_lock (const gchar *lock_directory,
2663 GError **err)
2664 {
2665 return gconf_get_lock_or_current_holder (lock_directory, NULL, err);
2666 }
2667
2668 gboolean
gconf_release_lock(GConfLock * lock,GError ** err)2669 gconf_release_lock (GConfLock *lock,
2670 GError **err)
2671 {
2672 gboolean retval;
2673 char *uniquefile;
2674
2675 retval = FALSE;
2676 uniquefile = NULL;
2677
2678 /* A paranoia check to avoid disaster if e.g.
2679 * some random client code opened and closed the
2680 * lockfile (maybe Nautilus checking its MIME type or
2681 * something)
2682 */
2683 if (lock->lock_fd < 0 ||
2684 file_locked_by_someone_else (lock->lock_fd))
2685 {
2686 g_set_error (err,
2687 GCONF_ERROR,
2688 GCONF_ERROR_FAILED,
2689 _("We didn't have the lock on file `%s', but we should have"),
2690 lock->iorfile);
2691 goto out;
2692 }
2693
2694 #ifndef G_OS_WIN32
2695
2696 /* To avoid annoying .nfs3435314513453145 files on unlink, which keep us
2697 * from removing the lock directory, we don't want to hold the
2698 * lockfile open after removing all links to it. But we can't
2699 * close it then unlink, because then we would be unlinking without
2700 * holding the lock. So, we create a unique filename and link it too
2701 * the locked file, then unlink the locked file, then drop our locks
2702 * and close file descriptors, then unlink the unique filename
2703 */
2704
2705 uniquefile = unique_filename (lock->lock_directory);
2706
2707 if (link (lock->iorfile, uniquefile) < 0)
2708 {
2709 g_set_error (err,
2710 GCONF_ERROR,
2711 GCONF_ERROR_FAILED,
2712 _("Failed to link '%s' to '%s': %s"),
2713 uniquefile, lock->iorfile, g_strerror (errno));
2714
2715 goto out;
2716 }
2717
2718 /* Note that we unlink while still holding the lock to avoid races */
2719 if (unlink (lock->iorfile) < 0)
2720 {
2721 g_set_error (err,
2722 GCONF_ERROR,
2723 GCONF_ERROR_FAILED,
2724 _("Failed to remove lock file `%s': %s"),
2725 lock->iorfile,
2726 g_strerror (errno));
2727 goto out;
2728 }
2729
2730 #endif
2731
2732 /* Now drop our lock */
2733 if (lock->lock_fd >= 0)
2734 {
2735 close (lock->lock_fd);
2736 lock->lock_fd = -1;
2737 }
2738
2739 #ifndef G_OS_WIN32
2740
2741 /* Now remove the temporary link we used to avoid .nfs351453 garbage */
2742 if (unlink (uniquefile) < 0)
2743 {
2744 g_set_error (err,
2745 GCONF_ERROR,
2746 GCONF_ERROR_FAILED,
2747 _("Failed to clean up file '%s': %s"),
2748 uniquefile, g_strerror (errno));
2749
2750 goto out;
2751 }
2752
2753 #endif
2754
2755 /* And finally clean up the directory - this would have failed if
2756 * we had .nfs323423423 junk
2757 */
2758 if (g_rmdir (lock->lock_directory) < 0)
2759 {
2760 g_set_error (err,
2761 GCONF_ERROR,
2762 GCONF_ERROR_FAILED,
2763 _("Failed to remove lock directory `%s': %s"),
2764 lock->lock_directory,
2765 g_strerror (errno));
2766 goto out;
2767 }
2768
2769 retval = TRUE;
2770
2771 out:
2772
2773 g_free (uniquefile);
2774 gconf_lock_destroy (lock);
2775 return retval;
2776 }
2777
2778 static CORBA_ORB gconf_orb = CORBA_OBJECT_NIL;
2779
2780 CORBA_ORB
gconf_orb_get(void)2781 gconf_orb_get (void)
2782 {
2783 if (gconf_orb == CORBA_OBJECT_NIL)
2784 {
2785 CORBA_Environment ev;
2786 int argc = 1;
2787 char *argv[] = { "gconf", NULL };
2788
2789 _gconf_init_i18n ();
2790
2791 CORBA_exception_init (&ev);
2792
2793 gconf_orb = CORBA_ORB_init (&argc, argv, "orbit-local-orb", &ev);
2794 g_assert (ev._major == CORBA_NO_EXCEPTION);
2795
2796 CORBA_exception_free (&ev);
2797 }
2798
2799 return gconf_orb;
2800 }
2801
2802 int
gconf_orb_release(void)2803 gconf_orb_release (void)
2804 {
2805 int ret = 0;
2806
2807 if (gconf_orb != CORBA_OBJECT_NIL)
2808 {
2809 CORBA_ORB orb = gconf_orb;
2810 CORBA_Environment ev;
2811
2812 gconf_orb = CORBA_OBJECT_NIL;
2813
2814 CORBA_exception_init (&ev);
2815
2816 CORBA_ORB_destroy (orb, &ev);
2817 CORBA_Object_release ((CORBA_Object)orb, &ev);
2818
2819 if (ev._major != CORBA_NO_EXCEPTION)
2820 {
2821 ret = 1;
2822 }
2823 CORBA_exception_free (&ev);
2824 }
2825
2826 return ret;
2827 }
2828
2829 char*
gconf_get_daemon_dir(void)2830 gconf_get_daemon_dir (void)
2831 {
2832 if (gconf_use_local_locks ())
2833 {
2834 char *s;
2835 char *subdir;
2836 const char *tmpdir;
2837
2838 subdir = g_strconcat ("gconfd-", g_get_user_name (), NULL);
2839
2840 if (g_getenv ("GCONF_TMPDIR"))
2841 tmpdir = g_getenv ("GCONF_TMPDIR");
2842 else if (g_getenv ("XDG_RUNTIME_DIR"))
2843 {
2844 g_free (subdir);
2845 subdir = g_strdup ("gconfd");
2846 tmpdir = g_getenv ("XDG_RUNTIME_DIR");
2847 }
2848 else
2849 tmpdir = g_get_tmp_dir ();
2850
2851 s = g_build_filename (tmpdir, subdir, NULL);
2852
2853 g_free (subdir);
2854
2855 return s;
2856 }
2857 else
2858 {
2859 #ifndef G_OS_WIN32
2860 const char *home = g_get_home_dir ();
2861 #else
2862 const char *home = _gconf_win32_get_home_dir ();
2863 #endif
2864 return g_strconcat (home, "/.gconfd", NULL);
2865 }
2866 }
2867
2868 ConfigServer
gconf_activate_server(gboolean start_if_not_found,GError ** error)2869 gconf_activate_server (gboolean start_if_not_found,
2870 GError **error)
2871 {
2872 ConfigServer server = CORBA_OBJECT_NIL;
2873 GString *failure_log;
2874 CORBA_Environment ev;
2875
2876 failure_log = g_string_new (NULL);
2877
2878 g_string_append (failure_log, " 1: ");
2879 server = gconf_get_server (start_if_not_found, failure_log);
2880
2881 /* Confirm server exists */
2882 CORBA_exception_init (&ev);
2883
2884 if (!CORBA_Object_is_nil (server, &ev))
2885 {
2886 ConfigServer_ping (server, &ev);
2887
2888 if (ev._major != CORBA_NO_EXCEPTION)
2889 {
2890 server = CORBA_OBJECT_NIL;
2891
2892 g_string_append_printf (failure_log,
2893 _("Server ping error: %s"),
2894 CORBA_exception_id (&ev));
2895 }
2896 }
2897
2898 CORBA_exception_free (&ev);
2899
2900 if (server != CORBA_OBJECT_NIL)
2901 {
2902 g_string_free (failure_log, TRUE);
2903 return server;
2904 }
2905
2906 if (server == CORBA_OBJECT_NIL &&
2907 error &&
2908 *error == NULL)
2909 g_set_error (error,
2910 GCONF_ERROR,
2911 GCONF_ERROR_NO_SERVER,
2912 _("Failed to contact configuration server; the most common cause is a missing or misconfigured D-Bus session bus daemon. See http://projects.gnome.org/gconf/ for information. (Details - %s)"),
2913 failure_log->len > 0 ? failure_log->str : _("none"));
2914
2915 g_string_free (failure_log, TRUE);
2916
2917 return server;
2918 }
2919
2920 gboolean
gconf_CORBA_Object_equal(gconstpointer a,gconstpointer b)2921 gconf_CORBA_Object_equal (gconstpointer a, gconstpointer b)
2922 {
2923 CORBA_Environment ev;
2924 CORBA_Object _obj_a = (gpointer)a;
2925 CORBA_Object _obj_b = (gpointer)b;
2926 gboolean retval;
2927
2928 CORBA_exception_init (&ev);
2929 retval = CORBA_Object_is_equivalent(_obj_a, _obj_b, &ev);
2930 CORBA_exception_free (&ev);
2931
2932 return retval;
2933 }
2934
2935 guint
gconf_CORBA_Object_hash(gconstpointer key)2936 gconf_CORBA_Object_hash (gconstpointer key)
2937 {
2938 CORBA_Environment ev;
2939 CORBA_Object _obj = (gpointer)key;
2940 CORBA_unsigned_long retval;
2941
2942 CORBA_exception_init (&ev);
2943 retval = CORBA_Object_hash(_obj, G_MAXUINT, &ev);
2944 CORBA_exception_free (&ev);
2945
2946 return retval;
2947 }
2948
2949 #endif /* HAVE_CORBA */
2950
2951 void
_gconf_init_i18n(void)2952 _gconf_init_i18n (void)
2953 {
2954 static gboolean done = FALSE;
2955
2956 if (!done)
2957 {
2958 bindtextdomain (GETTEXT_PACKAGE, GCONF_LOCALE_DIR);
2959 #ifdef HAVE_BIND_TEXTDOMAIN_CODESET
2960 bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
2961 #endif
2962 done = TRUE;
2963 }
2964 }
2965
2966 enum { UNKNOWN, LOCAL, NORMAL };
2967
2968 gboolean
gconf_use_local_locks(void)2969 gconf_use_local_locks (void)
2970 {
2971 static int local_locks = UNKNOWN;
2972
2973 if (local_locks == UNKNOWN)
2974 {
2975 const char *l =
2976 g_getenv ("GCONF_GLOBAL_LOCKS");
2977
2978 if (l && atoi (l) == 1)
2979 local_locks = NORMAL;
2980 else
2981 local_locks = LOCAL;
2982 }
2983
2984 return local_locks == LOCAL;
2985 }
2986