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 <config.h> |
---|
22 | #include "gconf-internals.h" |
---|
23 | #include "gconf-backend.h" |
---|
24 | #include "gconf-schema.h" |
---|
25 | #include <orb/orbit.h> |
---|
26 | #include <liboaf/liboaf.h> |
---|
27 | #include <string.h> |
---|
28 | #include <sys/stat.h> |
---|
29 | #include <sys/types.h> |
---|
30 | #include <unistd.h> |
---|
31 | #include <stdlib.h> |
---|
32 | #include <stdio.h> |
---|
33 | #include <fcntl.h> |
---|
34 | #include <errno.h> |
---|
35 | #include <ctype.h> |
---|
36 | #include <locale.h> |
---|
37 | #include <time.h> |
---|
38 | #include <math.h> |
---|
39 | |
---|
40 | static gboolean gconf_daemon_mode = FALSE; |
---|
41 | static gchar* daemon_ior = NULL; |
---|
42 | |
---|
43 | void |
---|
44 | gconf_set_daemon_mode(gboolean setting) |
---|
45 | { |
---|
46 | gconf_daemon_mode = setting; |
---|
47 | } |
---|
48 | |
---|
49 | gboolean |
---|
50 | gconf_in_daemon_mode(void) |
---|
51 | { |
---|
52 | return gconf_daemon_mode; |
---|
53 | } |
---|
54 | |
---|
55 | void |
---|
56 | gconf_set_daemon_ior(const gchar* ior) |
---|
57 | { |
---|
58 | if (daemon_ior != NULL) |
---|
59 | { |
---|
60 | g_free(daemon_ior); |
---|
61 | daemon_ior = NULL; |
---|
62 | } |
---|
63 | |
---|
64 | if (ior != NULL) |
---|
65 | daemon_ior = g_strdup(ior); |
---|
66 | } |
---|
67 | |
---|
68 | const gchar* |
---|
69 | gconf_get_daemon_ior(void) |
---|
70 | { |
---|
71 | return daemon_ior; |
---|
72 | } |
---|
73 | |
---|
74 | gchar* |
---|
75 | gconf_key_directory (const gchar* key) |
---|
76 | { |
---|
77 | const gchar* end; |
---|
78 | gchar* retval; |
---|
79 | int len; |
---|
80 | |
---|
81 | end = strrchr(key, '/'); |
---|
82 | |
---|
83 | if (end == NULL) |
---|
84 | { |
---|
85 | gconf_log(GCL_ERR, _("No '/' in key `%s'"), key); |
---|
86 | return NULL; |
---|
87 | } |
---|
88 | |
---|
89 | len = end-key+1; |
---|
90 | |
---|
91 | if (len == 1) |
---|
92 | { |
---|
93 | /* Root directory */ |
---|
94 | retval = g_strdup("/"); |
---|
95 | } |
---|
96 | else |
---|
97 | { |
---|
98 | retval = g_malloc(len); |
---|
99 | |
---|
100 | strncpy(retval, key, len); |
---|
101 | |
---|
102 | retval[len-1] = '\0'; |
---|
103 | } |
---|
104 | |
---|
105 | return retval; |
---|
106 | } |
---|
107 | |
---|
108 | const gchar* |
---|
109 | gconf_key_key (const gchar* key) |
---|
110 | { |
---|
111 | const gchar* end; |
---|
112 | |
---|
113 | end = strrchr(key, '/'); |
---|
114 | |
---|
115 | ++end; |
---|
116 | |
---|
117 | return end; |
---|
118 | } |
---|
119 | |
---|
120 | /* |
---|
121 | * Random stuff |
---|
122 | */ |
---|
123 | |
---|
124 | gboolean |
---|
125 | gconf_file_exists (const gchar* filename) |
---|
126 | { |
---|
127 | struct stat s; |
---|
128 | |
---|
129 | g_return_val_if_fail (filename != NULL,FALSE); |
---|
130 | |
---|
131 | return stat (filename, &s) == 0; |
---|
132 | } |
---|
133 | |
---|
134 | gboolean |
---|
135 | gconf_file_test(const gchar* filename, int test) |
---|
136 | { |
---|
137 | struct stat s; |
---|
138 | if(stat (filename, &s) != 0) |
---|
139 | return FALSE; |
---|
140 | if(!(test & GCONF_FILE_ISFILE) && S_ISREG(s.st_mode)) |
---|
141 | return FALSE; |
---|
142 | if(!(test & GCONF_FILE_ISLINK) && S_ISLNK(s.st_mode)) |
---|
143 | return FALSE; |
---|
144 | if(!(test & GCONF_FILE_ISDIR) && S_ISDIR(s.st_mode)) |
---|
145 | return FALSE; |
---|
146 | return TRUE; |
---|
147 | } |
---|
148 | |
---|
149 | GConfValue* |
---|
150 | gconf_value_from_corba_value(const ConfigValue* value) |
---|
151 | { |
---|
152 | GConfValue* gval; |
---|
153 | GConfValueType type = GCONF_VALUE_INVALID; |
---|
154 | |
---|
155 | switch (value->_d) |
---|
156 | { |
---|
157 | case InvalidVal: |
---|
158 | return NULL; |
---|
159 | break; |
---|
160 | case IntVal: |
---|
161 | type = GCONF_VALUE_INT; |
---|
162 | break; |
---|
163 | case StringVal: |
---|
164 | type = GCONF_VALUE_STRING; |
---|
165 | break; |
---|
166 | case FloatVal: |
---|
167 | type = GCONF_VALUE_FLOAT; |
---|
168 | break; |
---|
169 | case BoolVal: |
---|
170 | type = GCONF_VALUE_BOOL; |
---|
171 | break; |
---|
172 | case SchemaVal: |
---|
173 | type = GCONF_VALUE_SCHEMA; |
---|
174 | break; |
---|
175 | case ListVal: |
---|
176 | type = GCONF_VALUE_LIST; |
---|
177 | break; |
---|
178 | case PairVal: |
---|
179 | type = GCONF_VALUE_PAIR; |
---|
180 | break; |
---|
181 | default: |
---|
182 | gconf_log(GCL_DEBUG, "Invalid type in %s", G_GNUC_FUNCTION); |
---|
183 | return NULL; |
---|
184 | } |
---|
185 | |
---|
186 | g_assert(GCONF_VALUE_TYPE_VALID(type)); |
---|
187 | |
---|
188 | gval = gconf_value_new(type); |
---|
189 | |
---|
190 | switch (gval->type) |
---|
191 | { |
---|
192 | case GCONF_VALUE_INT: |
---|
193 | gconf_value_set_int(gval, value->_u.int_value); |
---|
194 | break; |
---|
195 | case GCONF_VALUE_STRING: |
---|
196 | gconf_value_set_string(gval, value->_u.string_value); |
---|
197 | break; |
---|
198 | case GCONF_VALUE_FLOAT: |
---|
199 | gconf_value_set_float(gval, value->_u.float_value); |
---|
200 | break; |
---|
201 | case GCONF_VALUE_BOOL: |
---|
202 | gconf_value_set_bool(gval, value->_u.bool_value); |
---|
203 | break; |
---|
204 | case GCONF_VALUE_SCHEMA: |
---|
205 | gconf_value_set_schema_nocopy(gval, |
---|
206 | gconf_schema_from_corba_schema(&(value->_u.schema_value))); |
---|
207 | break; |
---|
208 | case GCONF_VALUE_LIST: |
---|
209 | { |
---|
210 | GSList* list = NULL; |
---|
211 | guint i = 0; |
---|
212 | |
---|
213 | switch (value->_u.list_value.list_type) |
---|
214 | { |
---|
215 | case BIntVal: |
---|
216 | gconf_value_set_list_type(gval, GCONF_VALUE_INT); |
---|
217 | break; |
---|
218 | case BBoolVal: |
---|
219 | gconf_value_set_list_type(gval, GCONF_VALUE_BOOL); |
---|
220 | break; |
---|
221 | case BFloatVal: |
---|
222 | gconf_value_set_list_type(gval, GCONF_VALUE_FLOAT); |
---|
223 | break; |
---|
224 | case BStringVal: |
---|
225 | gconf_value_set_list_type(gval, GCONF_VALUE_STRING); |
---|
226 | break; |
---|
227 | case BInvalidVal: |
---|
228 | break; |
---|
229 | default: |
---|
230 | g_warning("Bizarre list type in %s", G_GNUC_FUNCTION); |
---|
231 | break; |
---|
232 | } |
---|
233 | |
---|
234 | if (gconf_value_get_list_type(gval) != GCONF_VALUE_INVALID) |
---|
235 | { |
---|
236 | i = 0; |
---|
237 | while (i < value->_u.list_value.seq._length) |
---|
238 | { |
---|
239 | GConfValue* val; |
---|
240 | |
---|
241 | /* This is a bit dubious; we cast a ConfigBasicValue to ConfigValue |
---|
242 | because they have the same initial members, but by the time |
---|
243 | the CORBA and C specs kick in, not sure we are guaranteed |
---|
244 | to be able to do this. |
---|
245 | */ |
---|
246 | val = gconf_value_from_corba_value((ConfigValue*)&value->_u.list_value.seq._buffer[i]); |
---|
247 | |
---|
248 | if (val == NULL) |
---|
249 | gconf_log(GCL_ERR, _("Couldn't interpret CORBA value for list element")); |
---|
250 | else if (val->type != gconf_value_get_list_type(gval)) |
---|
251 | gconf_log(GCL_ERR, _("Incorrect type for list element in %s"), G_GNUC_FUNCTION); |
---|
252 | else |
---|
253 | list = g_slist_prepend(list, val); |
---|
254 | |
---|
255 | ++i; |
---|
256 | } |
---|
257 | |
---|
258 | list = g_slist_reverse(list); |
---|
259 | |
---|
260 | gconf_value_set_list_nocopy(gval, list); |
---|
261 | } |
---|
262 | else |
---|
263 | { |
---|
264 | gconf_log(GCL_ERR, _("Received list from gconfd with a bad list type")); |
---|
265 | } |
---|
266 | } |
---|
267 | break; |
---|
268 | case GCONF_VALUE_PAIR: |
---|
269 | { |
---|
270 | g_return_val_if_fail(value->_u.pair_value._length == 2, gval); |
---|
271 | |
---|
272 | gconf_value_set_car_nocopy(gval, |
---|
273 | gconf_value_from_corba_value((ConfigValue*)&value->_u.list_value.seq._buffer[0])); |
---|
274 | |
---|
275 | gconf_value_set_cdr_nocopy(gval, |
---|
276 | gconf_value_from_corba_value((ConfigValue*)&value->_u.list_value.seq._buffer[1])); |
---|
277 | } |
---|
278 | break; |
---|
279 | default: |
---|
280 | g_assert_not_reached(); |
---|
281 | break; |
---|
282 | } |
---|
283 | |
---|
284 | return gval; |
---|
285 | } |
---|
286 | |
---|
287 | void |
---|
288 | fill_corba_value_from_gconf_value(GConfValue* value, |
---|
289 | ConfigValue* cv) |
---|
290 | { |
---|
291 | if (value == NULL) |
---|
292 | { |
---|
293 | cv->_d = InvalidVal; |
---|
294 | return; |
---|
295 | } |
---|
296 | |
---|
297 | switch (value->type) |
---|
298 | { |
---|
299 | case GCONF_VALUE_INT: |
---|
300 | cv->_d = IntVal; |
---|
301 | cv->_u.int_value = gconf_value_get_int(value); |
---|
302 | break; |
---|
303 | case GCONF_VALUE_STRING: |
---|
304 | cv->_d = StringVal; |
---|
305 | cv->_u.string_value = CORBA_string_dup((char*)gconf_value_get_string(value)); |
---|
306 | break; |
---|
307 | case GCONF_VALUE_FLOAT: |
---|
308 | cv->_d = FloatVal; |
---|
309 | cv->_u.float_value = gconf_value_get_float(value); |
---|
310 | break; |
---|
311 | case GCONF_VALUE_BOOL: |
---|
312 | cv->_d = BoolVal; |
---|
313 | cv->_u.bool_value = gconf_value_get_bool(value); |
---|
314 | break; |
---|
315 | case GCONF_VALUE_SCHEMA: |
---|
316 | cv->_d = SchemaVal; |
---|
317 | fill_corba_schema_from_gconf_schema(gconf_value_get_schema(value), |
---|
318 | &cv->_u.schema_value); |
---|
319 | break; |
---|
320 | case GCONF_VALUE_LIST: |
---|
321 | { |
---|
322 | guint n, i; |
---|
323 | GSList* list; |
---|
324 | |
---|
325 | cv->_d = ListVal; |
---|
326 | |
---|
327 | list = gconf_value_get_list(value); |
---|
328 | |
---|
329 | n = g_slist_length(list); |
---|
330 | |
---|
331 | cv->_u.list_value.seq._buffer = |
---|
332 | CORBA_sequence_ConfigBasicValue_allocbuf(n); |
---|
333 | cv->_u.list_value.seq._length = n; |
---|
334 | cv->_u.list_value.seq._maximum = n; |
---|
335 | CORBA_sequence_set_release(&cv->_u.list_value.seq, TRUE); |
---|
336 | |
---|
337 | switch (gconf_value_get_list_type(value)) |
---|
338 | { |
---|
339 | case GCONF_VALUE_INT: |
---|
340 | cv->_u.list_value.list_type = BIntVal; |
---|
341 | break; |
---|
342 | |
---|
343 | case GCONF_VALUE_BOOL: |
---|
344 | cv->_u.list_value.list_type = BBoolVal; |
---|
345 | break; |
---|
346 | |
---|
347 | case GCONF_VALUE_STRING: |
---|
348 | cv->_u.list_value.list_type = BStringVal; |
---|
349 | break; |
---|
350 | |
---|
351 | case GCONF_VALUE_FLOAT: |
---|
352 | cv->_u.list_value.list_type = BFloatVal; |
---|
353 | break; |
---|
354 | |
---|
355 | case GCONF_VALUE_SCHEMA: |
---|
356 | cv->_u.list_value.list_type = BSchemaVal; |
---|
357 | break; |
---|
358 | |
---|
359 | default: |
---|
360 | cv->_u.list_value.list_type = BInvalidVal; |
---|
361 | gconf_log(GCL_DEBUG, "Invalid list type in %s", G_GNUC_FUNCTION); |
---|
362 | break; |
---|
363 | } |
---|
364 | |
---|
365 | i= 0; |
---|
366 | while (list != NULL) |
---|
367 | { |
---|
368 | /* That dubious ConfigBasicValue->ConfigValue cast again */ |
---|
369 | fill_corba_value_from_gconf_value((GConfValue*)list->data, |
---|
370 | (ConfigValue*)&cv->_u.list_value.seq._buffer[i]); |
---|
371 | |
---|
372 | list = g_slist_next(list); |
---|
373 | ++i; |
---|
374 | } |
---|
375 | } |
---|
376 | break; |
---|
377 | case GCONF_VALUE_PAIR: |
---|
378 | { |
---|
379 | cv->_d = PairVal; |
---|
380 | |
---|
381 | cv->_u.pair_value._buffer = |
---|
382 | CORBA_sequence_ConfigBasicValue_allocbuf(2); |
---|
383 | cv->_u.pair_value._length = 2; |
---|
384 | cv->_u.pair_value._maximum = 2; |
---|
385 | CORBA_sequence_set_release(&cv->_u.pair_value, TRUE); |
---|
386 | |
---|
387 | /* dubious cast */ |
---|
388 | fill_corba_value_from_gconf_value(gconf_value_get_car(value), |
---|
389 | (ConfigValue*)&cv->_u.pair_value._buffer[0]); |
---|
390 | fill_corba_value_from_gconf_value(gconf_value_get_cdr(value), |
---|
391 | (ConfigValue*)&cv->_u.pair_value._buffer[1]); |
---|
392 | } |
---|
393 | break; |
---|
394 | |
---|
395 | case GCONF_VALUE_INVALID: |
---|
396 | cv->_d = InvalidVal; |
---|
397 | break; |
---|
398 | default: |
---|
399 | cv->_d = InvalidVal; |
---|
400 | gconf_log(GCL_DEBUG, "Unknown type in %s", G_GNUC_FUNCTION); |
---|
401 | break; |
---|
402 | } |
---|
403 | } |
---|
404 | |
---|
405 | ConfigValue* |
---|
406 | corba_value_from_gconf_value(GConfValue* value) |
---|
407 | { |
---|
408 | ConfigValue* cv; |
---|
409 | |
---|
410 | cv = ConfigValue__alloc(); |
---|
411 | |
---|
412 | fill_corba_value_from_gconf_value(value, cv); |
---|
413 | |
---|
414 | return cv; |
---|
415 | } |
---|
416 | |
---|
417 | ConfigValue* |
---|
418 | invalid_corba_value() |
---|
419 | { |
---|
420 | ConfigValue* cv; |
---|
421 | |
---|
422 | cv = ConfigValue__alloc(); |
---|
423 | |
---|
424 | cv->_d = InvalidVal; |
---|
425 | |
---|
426 | return cv; |
---|
427 | } |
---|
428 | |
---|
429 | gchar* |
---|
430 | gconf_object_to_string (CORBA_Object obj, |
---|
431 | GError **err) |
---|
432 | { |
---|
433 | CORBA_Environment ev; |
---|
434 | gchar *ior; |
---|
435 | gchar *retval; |
---|
436 | |
---|
437 | CORBA_exception_init (&ev); |
---|
438 | |
---|
439 | ior = CORBA_ORB_object_to_string (oaf_orb_get (), obj, &ev); |
---|
440 | |
---|
441 | if (ior == NULL) |
---|
442 | { |
---|
443 | gconf_set_error (err, |
---|
444 | GCONF_ERROR_FAILED, |
---|
445 | _("Failed to convert object to IOR")); |
---|
446 | |
---|
447 | return NULL; |
---|
448 | } |
---|
449 | |
---|
450 | retval = g_strdup (ior); |
---|
451 | |
---|
452 | CORBA_free (ior); |
---|
453 | |
---|
454 | return retval; |
---|
455 | } |
---|
456 | |
---|
457 | static ConfigValueType |
---|
458 | corba_type_from_gconf_type(GConfValueType type) |
---|
459 | { |
---|
460 | switch (type) |
---|
461 | { |
---|
462 | case GCONF_VALUE_INT: |
---|
463 | return IntVal; |
---|
464 | case GCONF_VALUE_BOOL: |
---|
465 | return BoolVal; |
---|
466 | case GCONF_VALUE_FLOAT: |
---|
467 | return FloatVal; |
---|
468 | case GCONF_VALUE_INVALID: |
---|
469 | return InvalidVal; |
---|
470 | case GCONF_VALUE_STRING: |
---|
471 | return StringVal; |
---|
472 | case GCONF_VALUE_SCHEMA: |
---|
473 | return SchemaVal; |
---|
474 | case GCONF_VALUE_LIST: |
---|
475 | return ListVal; |
---|
476 | case GCONF_VALUE_PAIR: |
---|
477 | return PairVal; |
---|
478 | default: |
---|
479 | g_assert_not_reached(); |
---|
480 | return InvalidVal; |
---|
481 | } |
---|
482 | } |
---|
483 | |
---|
484 | static GConfValueType |
---|
485 | gconf_type_from_corba_type(ConfigValueType type) |
---|
486 | { |
---|
487 | switch (type) |
---|
488 | { |
---|
489 | case InvalidVal: |
---|
490 | return GCONF_VALUE_INVALID; |
---|
491 | case StringVal: |
---|
492 | return GCONF_VALUE_STRING; |
---|
493 | case IntVal: |
---|
494 | return GCONF_VALUE_INT; |
---|
495 | case FloatVal: |
---|
496 | return GCONF_VALUE_FLOAT; |
---|
497 | case SchemaVal: |
---|
498 | return GCONF_VALUE_SCHEMA; |
---|
499 | case BoolVal: |
---|
500 | return GCONF_VALUE_BOOL; |
---|
501 | case ListVal: |
---|
502 | return GCONF_VALUE_LIST; |
---|
503 | case PairVal: |
---|
504 | return GCONF_VALUE_PAIR; |
---|
505 | default: |
---|
506 | g_assert_not_reached(); |
---|
507 | return GCONF_VALUE_INVALID; |
---|
508 | } |
---|
509 | } |
---|
510 | |
---|
511 | void |
---|
512 | fill_corba_schema_from_gconf_schema(GConfSchema* sc, |
---|
513 | ConfigSchema* cs) |
---|
514 | { |
---|
515 | cs->value_type = corba_type_from_gconf_type(sc->type); |
---|
516 | cs->value_list_type = corba_type_from_gconf_type(sc->list_type); |
---|
517 | cs->value_car_type = corba_type_from_gconf_type(sc->car_type); |
---|
518 | cs->value_cdr_type = corba_type_from_gconf_type(sc->cdr_type); |
---|
519 | |
---|
520 | cs->locale = CORBA_string_dup(sc->locale ? sc->locale : ""); |
---|
521 | cs->short_desc = CORBA_string_dup(sc->short_desc ? sc->short_desc : ""); |
---|
522 | cs->long_desc = CORBA_string_dup(sc->long_desc ? sc->long_desc : ""); |
---|
523 | cs->owner = CORBA_string_dup(sc->owner ? sc->owner : ""); |
---|
524 | |
---|
525 | { |
---|
526 | gchar* encoded; |
---|
527 | GConfValue* default_val; |
---|
528 | |
---|
529 | default_val = gconf_schema_get_default_value(sc); |
---|
530 | |
---|
531 | if (default_val) |
---|
532 | { |
---|
533 | encoded = gconf_value_encode(default_val); |
---|
534 | |
---|
535 | g_assert(encoded != NULL); |
---|
536 | |
---|
537 | cs->encoded_default_value = CORBA_string_dup(encoded); |
---|
538 | |
---|
539 | g_free(encoded); |
---|
540 | } |
---|
541 | else |
---|
542 | cs->encoded_default_value = CORBA_string_dup(""); |
---|
543 | } |
---|
544 | } |
---|
545 | |
---|
546 | ConfigSchema* |
---|
547 | corba_schema_from_gconf_schema(GConfSchema* sc) |
---|
548 | { |
---|
549 | ConfigSchema* cs; |
---|
550 | |
---|
551 | cs = ConfigSchema__alloc(); |
---|
552 | |
---|
553 | fill_corba_schema_from_gconf_schema(sc, cs); |
---|
554 | |
---|
555 | return cs; |
---|
556 | } |
---|
557 | |
---|
558 | GConfSchema* |
---|
559 | gconf_schema_from_corba_schema(const ConfigSchema* cs) |
---|
560 | { |
---|
561 | GConfSchema* sc; |
---|
562 | GConfValueType type = GCONF_VALUE_INVALID; |
---|
563 | GConfValueType list_type = GCONF_VALUE_INVALID; |
---|
564 | GConfValueType car_type = GCONF_VALUE_INVALID; |
---|
565 | GConfValueType cdr_type = GCONF_VALUE_INVALID; |
---|
566 | |
---|
567 | type = gconf_type_from_corba_type(cs->value_type); |
---|
568 | list_type = gconf_type_from_corba_type(cs->value_list_type); |
---|
569 | car_type = gconf_type_from_corba_type(cs->value_car_type); |
---|
570 | cdr_type = gconf_type_from_corba_type(cs->value_cdr_type); |
---|
571 | |
---|
572 | sc = gconf_schema_new(); |
---|
573 | |
---|
574 | gconf_schema_set_type(sc, type); |
---|
575 | gconf_schema_set_list_type(sc, list_type); |
---|
576 | gconf_schema_set_car_type(sc, car_type); |
---|
577 | gconf_schema_set_cdr_type(sc, cdr_type); |
---|
578 | |
---|
579 | if (*cs->locale != '\0') |
---|
580 | gconf_schema_set_locale(sc, cs->locale); |
---|
581 | |
---|
582 | if (*cs->short_desc != '\0') |
---|
583 | gconf_schema_set_short_desc(sc, cs->short_desc); |
---|
584 | |
---|
585 | if (*cs->long_desc != '\0') |
---|
586 | gconf_schema_set_long_desc(sc, cs->long_desc); |
---|
587 | |
---|
588 | if (*cs->owner != '\0') |
---|
589 | gconf_schema_set_owner(sc, cs->owner); |
---|
590 | |
---|
591 | { |
---|
592 | GConfValue* val; |
---|
593 | |
---|
594 | val = gconf_value_decode(cs->encoded_default_value); |
---|
595 | |
---|
596 | if (val) |
---|
597 | gconf_schema_set_default_value_nocopy(sc, val); |
---|
598 | } |
---|
599 | |
---|
600 | return sc; |
---|
601 | } |
---|
602 | |
---|
603 | const gchar* |
---|
604 | gconf_value_type_to_string(GConfValueType type) |
---|
605 | { |
---|
606 | switch (type) |
---|
607 | { |
---|
608 | case GCONF_VALUE_INT: |
---|
609 | return "int"; |
---|
610 | break; |
---|
611 | case GCONF_VALUE_STRING: |
---|
612 | return "string"; |
---|
613 | break; |
---|
614 | case GCONF_VALUE_FLOAT: |
---|
615 | return "float"; |
---|
616 | break; |
---|
617 | case GCONF_VALUE_BOOL: |
---|
618 | return "bool"; |
---|
619 | break; |
---|
620 | case GCONF_VALUE_SCHEMA: |
---|
621 | return "schema"; |
---|
622 | break; |
---|
623 | case GCONF_VALUE_LIST: |
---|
624 | return "list"; |
---|
625 | break; |
---|
626 | case GCONF_VALUE_PAIR: |
---|
627 | return "pair"; |
---|
628 | break; |
---|
629 | case GCONF_VALUE_INVALID: |
---|
630 | return "*invalid*"; |
---|
631 | break; |
---|
632 | default: |
---|
633 | g_assert_not_reached(); |
---|
634 | return NULL; /* for warnings */ |
---|
635 | break; |
---|
636 | } |
---|
637 | } |
---|
638 | |
---|
639 | GConfValueType |
---|
640 | gconf_value_type_from_string(const gchar* type_str) |
---|
641 | { |
---|
642 | if (strcmp(type_str, "int") == 0) |
---|
643 | return GCONF_VALUE_INT; |
---|
644 | else if (strcmp(type_str, "float") == 0) |
---|
645 | return GCONF_VALUE_FLOAT; |
---|
646 | else if (strcmp(type_str, "string") == 0) |
---|
647 | return GCONF_VALUE_STRING; |
---|
648 | else if (strcmp(type_str, "bool") == 0) |
---|
649 | return GCONF_VALUE_BOOL; |
---|
650 | else if (strcmp(type_str, "schema") == 0) |
---|
651 | return GCONF_VALUE_SCHEMA; |
---|
652 | else if (strcmp(type_str, "list") == 0) |
---|
653 | return GCONF_VALUE_LIST; |
---|
654 | else if (strcmp(type_str, "pair") == 0) |
---|
655 | return GCONF_VALUE_PAIR; |
---|
656 | else |
---|
657 | return GCONF_VALUE_INVALID; |
---|
658 | } |
---|
659 | |
---|
660 | /* |
---|
661 | * Config files (yikes! we can't store our config in GConf!) |
---|
662 | */ |
---|
663 | |
---|
664 | static gchar* |
---|
665 | unquote_string(gchar* s) |
---|
666 | { |
---|
667 | gchar* end; |
---|
668 | |
---|
669 | /* Strip whitespace and first quote from front of string */ |
---|
670 | while (*s && (isspace(*s) || (*s == '"'))) |
---|
671 | ++s; |
---|
672 | |
---|
673 | end = s; |
---|
674 | while (*end) |
---|
675 | ++end; |
---|
676 | |
---|
677 | --end; /* one back from '\0' */ |
---|
678 | |
---|
679 | /* Strip whitespace and last quote from end of string */ |
---|
680 | while ((end > s) && (isspace(*end) || (*end == '"'))) |
---|
681 | { |
---|
682 | *end = '\0'; |
---|
683 | --end; |
---|
684 | } |
---|
685 | |
---|
686 | return s; |
---|
687 | } |
---|
688 | |
---|
689 | static const gchar* |
---|
690 | get_variable(const gchar* varname) |
---|
691 | { |
---|
692 | /* These first two DO NOT use environment variables, which |
---|
693 | makes things a bit more "secure" in some sense |
---|
694 | */ |
---|
695 | if (strcmp(varname, "HOME") == 0) |
---|
696 | { |
---|
697 | return g_get_home_dir(); |
---|
698 | } |
---|
699 | else if (strcmp(varname, "USER") == 0) |
---|
700 | { |
---|
701 | return g_get_user_name(); |
---|
702 | } |
---|
703 | else if (varname[0] == 'E' && |
---|
704 | varname[1] == 'N' && |
---|
705 | varname[2] == 'V' && |
---|
706 | varname[3] == '_') |
---|
707 | { |
---|
708 | /* This is magic: if a variable called ENV_FOO is used, |
---|
709 | then the environment variable FOO is checked */ |
---|
710 | gchar* envvar = getenv(&varname[4]); |
---|
711 | |
---|
712 | if (envvar) |
---|
713 | return envvar; |
---|
714 | else |
---|
715 | return ""; |
---|
716 | } |
---|
717 | else |
---|
718 | return ""; |
---|
719 | } |
---|
720 | |
---|
721 | static gchar* |
---|
722 | subst_variables(const gchar* src) |
---|
723 | { |
---|
724 | const gchar* iter; |
---|
725 | gchar* retval; |
---|
726 | guint retval_len; |
---|
727 | guint pos; |
---|
728 | |
---|
729 | g_return_val_if_fail(src != NULL, NULL); |
---|
730 | |
---|
731 | retval_len = strlen(src) + 1; |
---|
732 | pos = 0; |
---|
733 | |
---|
734 | retval = g_malloc0(retval_len+3); /* add 3 just to avoid off-by-one |
---|
735 | segvs - yeah I know it bugs |
---|
736 | you, but C sucks */ |
---|
737 | |
---|
738 | iter = src; |
---|
739 | |
---|
740 | while (*iter) |
---|
741 | { |
---|
742 | gboolean performed_subst = FALSE; |
---|
743 | |
---|
744 | if (pos >= retval_len) |
---|
745 | { |
---|
746 | retval_len *= 2; |
---|
747 | retval = g_realloc(retval, retval_len+3); /* add 3 for luck */ |
---|
748 | } |
---|
749 | |
---|
750 | if (*iter == '$' && *(iter+1) == '(') |
---|
751 | { |
---|
752 | const gchar* varstart = iter + 2; |
---|
753 | const gchar* varend = strchr(varstart, ')'); |
---|
754 | |
---|
755 | if (varend != NULL) |
---|
756 | { |
---|
757 | char* varname; |
---|
758 | const gchar* varval; |
---|
759 | guint varval_len; |
---|
760 | |
---|
761 | performed_subst = TRUE; |
---|
762 | |
---|
763 | varname = g_strndup(varstart, varend - varstart); |
---|
764 | |
---|
765 | varval = get_variable(varname); |
---|
766 | g_free(varname); |
---|
767 | |
---|
768 | varval_len = strlen(varval); |
---|
769 | |
---|
770 | if ((retval_len - pos) < varval_len) |
---|
771 | { |
---|
772 | retval_len *= 2; |
---|
773 | retval = g_realloc(retval, retval_len+3); |
---|
774 | } |
---|
775 | |
---|
776 | strcpy(&retval[pos], varval); |
---|
777 | pos += varval_len; |
---|
778 | |
---|
779 | iter = varend + 1; |
---|
780 | } |
---|
781 | } |
---|
782 | |
---|
783 | if (!performed_subst) |
---|
784 | { |
---|
785 | retval[pos] = *iter; |
---|
786 | ++pos; |
---|
787 | ++iter; |
---|
788 | } |
---|
789 | } |
---|
790 | retval[pos] = '\0'; |
---|
791 | |
---|
792 | return retval; |
---|
793 | } |
---|
794 | |
---|
795 | gchar** |
---|
796 | gconf_load_source_path(const gchar* filename, GError** err) |
---|
797 | { |
---|
798 | FILE* f; |
---|
799 | GSList* l = NULL; |
---|
800 | gchar** addresses; |
---|
801 | gchar buf[512]; |
---|
802 | GSList* tmp; |
---|
803 | guint n; |
---|
804 | |
---|
805 | f = fopen(filename, "r"); |
---|
806 | |
---|
807 | if (f == NULL) |
---|
808 | { |
---|
809 | if (err) |
---|
810 | *err = gconf_error_new(GCONF_ERROR_FAILED, |
---|
811 | _("Couldn't open path file `%s': %s\n"), |
---|
812 | filename, |
---|
813 | strerror(errno)); |
---|
814 | return NULL; |
---|
815 | } |
---|
816 | |
---|
817 | while (fgets(buf, 512, f) != NULL) |
---|
818 | { |
---|
819 | gchar* s = buf; |
---|
820 | |
---|
821 | while (*s && isspace(*s)) |
---|
822 | ++s; |
---|
823 | |
---|
824 | if (*s == '#') |
---|
825 | { |
---|
826 | /* Allow comments, why not */ |
---|
827 | } |
---|
828 | else if (*s == '\0') |
---|
829 | { |
---|
830 | /* Blank line */ |
---|
831 | } |
---|
832 | else if (strncmp("include", s, 7) == 0) |
---|
833 | { |
---|
834 | gchar* unq; |
---|
835 | gchar** included; |
---|
836 | |
---|
837 | s += 7; |
---|
838 | |
---|
839 | unq = unquote_string(s); |
---|
840 | |
---|
841 | included = gconf_load_source_path(unq, NULL); |
---|
842 | |
---|
843 | if (included != NULL) |
---|
844 | { |
---|
845 | gchar** iter = included; |
---|
846 | |
---|
847 | while (*iter) |
---|
848 | { |
---|
849 | l = g_slist_prepend(l, *iter); /* Note that we won't free *included */ |
---|
850 | ++iter; |
---|
851 | } |
---|
852 | |
---|
853 | g_free(included); /* Only the array, not the contained strings */ |
---|
854 | } |
---|
855 | } |
---|
856 | else |
---|
857 | { |
---|
858 | gchar* unq; |
---|
859 | gchar* varsubst; |
---|
860 | |
---|
861 | unq = unquote_string(buf); |
---|
862 | varsubst = subst_variables(unq); |
---|
863 | |
---|
864 | if (*varsubst != '\0') /* Drop lines with just two quote marks or something */ |
---|
865 | { |
---|
866 | gconf_log(GCL_INFO, _("Adding source `%s'\n"), varsubst); |
---|
867 | l = g_slist_prepend(l, g_strdup(varsubst)); |
---|
868 | } |
---|
869 | g_free(varsubst); |
---|
870 | } |
---|
871 | } |
---|
872 | |
---|
873 | if (ferror(f)) |
---|
874 | { |
---|
875 | /* This should basically never happen */ |
---|
876 | if (err) |
---|
877 | *err = gconf_error_new(GCONF_ERROR_FAILED, |
---|
878 | _("Read error on file `%s': %s\n"), |
---|
879 | filename, |
---|
880 | strerror(errno)); |
---|
881 | /* don't return, we want to go ahead and return any |
---|
882 | addresses we already loaded. */ |
---|
883 | } |
---|
884 | |
---|
885 | fclose(f); |
---|
886 | |
---|
887 | /* This will make sense if you realize that we reversed the list |
---|
888 | as we loaded it, and are now reversing it to be correct again. |
---|
889 | */ |
---|
890 | |
---|
891 | if (l == NULL) |
---|
892 | return NULL; |
---|
893 | |
---|
894 | n = g_slist_length(l); |
---|
895 | |
---|
896 | g_assert(n > 0); |
---|
897 | |
---|
898 | addresses = g_malloc0(sizeof(gchar*) * (n+1)); |
---|
899 | |
---|
900 | addresses[n] = NULL; |
---|
901 | |
---|
902 | --n; |
---|
903 | tmp = l; |
---|
904 | |
---|
905 | while (tmp != NULL) |
---|
906 | { |
---|
907 | addresses[n] = tmp->data; |
---|
908 | |
---|
909 | tmp = g_slist_next(tmp); |
---|
910 | --n; |
---|
911 | } |
---|
912 | |
---|
913 | g_assert(addresses[0] != NULL); /* since we used malloc0 this detects bad logic */ |
---|
914 | |
---|
915 | return addresses; |
---|
916 | } |
---|
917 | |
---|
918 | /* This should also support concatting filesystem dirs and keys, |
---|
919 | or dir and subdir. |
---|
920 | */ |
---|
921 | gchar* |
---|
922 | gconf_concat_dir_and_key(const gchar* dir, const gchar* key) |
---|
923 | { |
---|
924 | guint dirlen; |
---|
925 | guint keylen; |
---|
926 | gchar* retval; |
---|
927 | |
---|
928 | g_return_val_if_fail(dir != NULL, NULL); |
---|
929 | g_return_val_if_fail(key != NULL, NULL); |
---|
930 | g_return_val_if_fail(*dir == '/', NULL); |
---|
931 | |
---|
932 | dirlen = strlen(dir); |
---|
933 | keylen = strlen(key); |
---|
934 | |
---|
935 | retval = g_malloc0(dirlen+keylen+3); /* auto-null-terminate */ |
---|
936 | |
---|
937 | strcpy(retval, dir); |
---|
938 | |
---|
939 | if (dir[dirlen-1] == '/') |
---|
940 | { |
---|
941 | /* dir ends in slash, strip key slash if needed */ |
---|
942 | if (*key == '/') |
---|
943 | ++key; |
---|
944 | |
---|
945 | strcpy((retval+dirlen), key); |
---|
946 | } |
---|
947 | else |
---|
948 | { |
---|
949 | /* Dir doesn't end in slash, add slash if key lacks one. */ |
---|
950 | gchar* dest = retval + dirlen; |
---|
951 | |
---|
952 | if (*key != '/') |
---|
953 | { |
---|
954 | *dest = '/'; |
---|
955 | ++dest; |
---|
956 | } |
---|
957 | |
---|
958 | strcpy(dest, key); |
---|
959 | } |
---|
960 | |
---|
961 | return retval; |
---|
962 | } |
---|
963 | |
---|
964 | gulong |
---|
965 | gconf_string_to_gulong(const gchar* str) |
---|
966 | { |
---|
967 | gulong retval; |
---|
968 | gchar *end; |
---|
969 | errno = 0; |
---|
970 | retval = strtoul(str, &end, 10); |
---|
971 | if (end == str || errno != 0) |
---|
972 | retval = 0; |
---|
973 | |
---|
974 | return retval; |
---|
975 | } |
---|
976 | |
---|
977 | gboolean |
---|
978 | gconf_string_to_double(const gchar* str, gdouble* retloc) |
---|
979 | { |
---|
980 | int res; |
---|
981 | char *old_locale; |
---|
982 | |
---|
983 | /* make sure we write values to files in a consistent manner */ |
---|
984 | old_locale = g_strdup (setlocale (LC_NUMERIC, NULL)); |
---|
985 | setlocale (LC_NUMERIC, "C"); |
---|
986 | |
---|
987 | *retloc = 0.0; |
---|
988 | res = sscanf (str, "%lf", retloc); |
---|
989 | |
---|
990 | setlocale (LC_NUMERIC, old_locale); |
---|
991 | g_free (old_locale); |
---|
992 | |
---|
993 | if (res == 1) |
---|
994 | return TRUE; |
---|
995 | else |
---|
996 | return FALSE; |
---|
997 | } |
---|
998 | |
---|
999 | gchar* |
---|
1000 | gconf_double_to_string(gdouble val) |
---|
1001 | { |
---|
1002 | char str[101 + DBL_DIG]; |
---|
1003 | char *old_locale; |
---|
1004 | |
---|
1005 | /* make sure we write values to files in a consistent manner */ |
---|
1006 | old_locale = g_strdup (setlocale (LC_NUMERIC, NULL)); |
---|
1007 | setlocale (LC_NUMERIC, "C"); |
---|
1008 | |
---|
1009 | if (fabs (val) < 1e9 && fabs (val) > 1e-5) |
---|
1010 | snprintf (str, 100 + DBL_DIG, "%.*g", DBL_DIG, val); |
---|
1011 | else |
---|
1012 | snprintf (str, 100 + DBL_DIG, "%f", val); |
---|
1013 | |
---|
1014 | setlocale (LC_NUMERIC, old_locale); |
---|
1015 | g_free (old_locale); |
---|
1016 | |
---|
1017 | return g_strdup(str); |
---|
1018 | } |
---|
1019 | |
---|
1020 | const gchar* |
---|
1021 | gconf_current_locale(void) |
---|
1022 | { |
---|
1023 | #ifdef HAVE_LC_MESSAGES |
---|
1024 | return setlocale(LC_MESSAGES, NULL); |
---|
1025 | #else |
---|
1026 | return setlocale(LC_CTYPE, NULL); |
---|
1027 | #endif |
---|
1028 | } |
---|
1029 | |
---|
1030 | /* |
---|
1031 | * Log |
---|
1032 | */ |
---|
1033 | |
---|
1034 | gchar* |
---|
1035 | gconf_quote_percents(const gchar* src) |
---|
1036 | { |
---|
1037 | gchar* dest; |
---|
1038 | const gchar* s; |
---|
1039 | gchar* d; |
---|
1040 | |
---|
1041 | g_return_val_if_fail(src != NULL, NULL); |
---|
1042 | |
---|
1043 | /* waste memory! woo-hoo! */ |
---|
1044 | dest = g_malloc0(strlen(src)*2+4); |
---|
1045 | |
---|
1046 | d = dest; |
---|
1047 | |
---|
1048 | s = src; |
---|
1049 | while (*s) |
---|
1050 | { |
---|
1051 | switch (*s) |
---|
1052 | { |
---|
1053 | case '%': |
---|
1054 | { |
---|
1055 | *d = '%'; |
---|
1056 | ++d; |
---|
1057 | *d = '%'; |
---|
1058 | ++d; |
---|
1059 | } |
---|
1060 | break; |
---|
1061 | |
---|
1062 | default: |
---|
1063 | { |
---|
1064 | *d = *s; |
---|
1065 | ++d; |
---|
1066 | } |
---|
1067 | break; |
---|
1068 | } |
---|
1069 | ++s; |
---|
1070 | } |
---|
1071 | |
---|
1072 | /* End with NULL */ |
---|
1073 | *d = '\0'; |
---|
1074 | |
---|
1075 | return dest; |
---|
1076 | } |
---|
1077 | |
---|
1078 | #include <syslog.h> |
---|
1079 | |
---|
1080 | void |
---|
1081 | gconf_log(GConfLogPriority pri, const gchar* fmt, ...) |
---|
1082 | { |
---|
1083 | gchar* msg; |
---|
1084 | va_list args; |
---|
1085 | int syslog_pri = LOG_DEBUG; |
---|
1086 | |
---|
1087 | #ifndef GCONF_ENABLE_DEBUG |
---|
1088 | if (pri == GCL_DEBUG) |
---|
1089 | return; |
---|
1090 | #endif |
---|
1091 | |
---|
1092 | va_start (args, fmt); |
---|
1093 | msg = g_strdup_vprintf(fmt, args); |
---|
1094 | va_end (args); |
---|
1095 | |
---|
1096 | if (gconf_daemon_mode) |
---|
1097 | { |
---|
1098 | switch (pri) |
---|
1099 | { |
---|
1100 | case GCL_EMERG: |
---|
1101 | syslog_pri = LOG_EMERG; |
---|
1102 | break; |
---|
1103 | |
---|
1104 | case GCL_ALERT: |
---|
1105 | syslog_pri = LOG_ALERT; |
---|
1106 | break; |
---|
1107 | |
---|
1108 | case GCL_CRIT: |
---|
1109 | syslog_pri = LOG_CRIT; |
---|
1110 | break; |
---|
1111 | |
---|
1112 | case GCL_ERR: |
---|
1113 | syslog_pri = LOG_ERR; |
---|
1114 | break; |
---|
1115 | |
---|
1116 | case GCL_WARNING: |
---|
1117 | syslog_pri = LOG_WARNING; |
---|
1118 | break; |
---|
1119 | |
---|
1120 | case GCL_NOTICE: |
---|
1121 | syslog_pri = LOG_NOTICE; |
---|
1122 | break; |
---|
1123 | |
---|
1124 | case GCL_INFO: |
---|
1125 | syslog_pri = LOG_INFO; |
---|
1126 | break; |
---|
1127 | |
---|
1128 | case GCL_DEBUG: |
---|
1129 | syslog_pri = LOG_DEBUG; |
---|
1130 | break; |
---|
1131 | |
---|
1132 | default: |
---|
1133 | g_assert_not_reached(); |
---|
1134 | break; |
---|
1135 | } |
---|
1136 | |
---|
1137 | syslog(syslog_pri, "%s", msg); |
---|
1138 | } |
---|
1139 | else |
---|
1140 | { |
---|
1141 | switch (pri) |
---|
1142 | { |
---|
1143 | case GCL_EMERG: |
---|
1144 | case GCL_ALERT: |
---|
1145 | case GCL_CRIT: |
---|
1146 | case GCL_ERR: |
---|
1147 | case GCL_WARNING: |
---|
1148 | fprintf(stderr, "%s\n", msg); |
---|
1149 | break; |
---|
1150 | |
---|
1151 | case GCL_NOTICE: |
---|
1152 | case GCL_INFO: |
---|
1153 | case GCL_DEBUG: |
---|
1154 | printf("%s\n", msg); |
---|
1155 | break; |
---|
1156 | |
---|
1157 | default: |
---|
1158 | g_assert_not_reached(); |
---|
1159 | break; |
---|
1160 | } |
---|
1161 | } |
---|
1162 | |
---|
1163 | g_free(msg); |
---|
1164 | } |
---|
1165 | |
---|
1166 | /* |
---|
1167 | * List/pair conversion |
---|
1168 | */ |
---|
1169 | |
---|
1170 | GConfValue* |
---|
1171 | gconf_value_list_from_primitive_list(GConfValueType list_type, GSList* list) |
---|
1172 | { |
---|
1173 | GSList* value_list; |
---|
1174 | GSList* tmp; |
---|
1175 | |
---|
1176 | g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL); |
---|
1177 | g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL); |
---|
1178 | g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL); |
---|
1179 | |
---|
1180 | value_list = NULL; |
---|
1181 | |
---|
1182 | tmp = list; |
---|
1183 | |
---|
1184 | while (tmp != NULL) |
---|
1185 | { |
---|
1186 | GConfValue* val; |
---|
1187 | |
---|
1188 | val = gconf_value_new(list_type); |
---|
1189 | |
---|
1190 | switch (list_type) |
---|
1191 | { |
---|
1192 | case GCONF_VALUE_INT: |
---|
1193 | gconf_value_set_int(val, GPOINTER_TO_INT(tmp->data)); |
---|
1194 | break; |
---|
1195 | |
---|
1196 | case GCONF_VALUE_BOOL: |
---|
1197 | gconf_value_set_bool(val, GPOINTER_TO_INT(tmp->data)); |
---|
1198 | break; |
---|
1199 | |
---|
1200 | case GCONF_VALUE_FLOAT: |
---|
1201 | gconf_value_set_float(val, *((gdouble*)tmp->data)); |
---|
1202 | break; |
---|
1203 | |
---|
1204 | case GCONF_VALUE_STRING: |
---|
1205 | gconf_value_set_string(val, tmp->data); |
---|
1206 | break; |
---|
1207 | |
---|
1208 | case GCONF_VALUE_SCHEMA: |
---|
1209 | gconf_value_set_schema(val, tmp->data); |
---|
1210 | break; |
---|
1211 | |
---|
1212 | default: |
---|
1213 | g_assert_not_reached(); |
---|
1214 | break; |
---|
1215 | } |
---|
1216 | |
---|
1217 | value_list = g_slist_prepend(value_list, val); |
---|
1218 | |
---|
1219 | tmp = g_slist_next(tmp); |
---|
1220 | } |
---|
1221 | |
---|
1222 | /* Get it in the right order. */ |
---|
1223 | value_list = g_slist_reverse(value_list); |
---|
1224 | |
---|
1225 | { |
---|
1226 | GConfValue* value_with_list; |
---|
1227 | |
---|
1228 | value_with_list = gconf_value_new(GCONF_VALUE_LIST); |
---|
1229 | gconf_value_set_list_type(value_with_list, list_type); |
---|
1230 | gconf_value_set_list_nocopy(value_with_list, value_list); |
---|
1231 | |
---|
1232 | return value_with_list; |
---|
1233 | } |
---|
1234 | } |
---|
1235 | |
---|
1236 | |
---|
1237 | static GConfValue* |
---|
1238 | from_primitive(GConfValueType type, gconstpointer address) |
---|
1239 | { |
---|
1240 | GConfValue* val; |
---|
1241 | |
---|
1242 | val = gconf_value_new(type); |
---|
1243 | |
---|
1244 | switch (type) |
---|
1245 | { |
---|
1246 | case GCONF_VALUE_INT: |
---|
1247 | gconf_value_set_int(val, *((const gint*)address)); |
---|
1248 | break; |
---|
1249 | |
---|
1250 | case GCONF_VALUE_BOOL: |
---|
1251 | gconf_value_set_bool(val, *((const gboolean*)address)); |
---|
1252 | break; |
---|
1253 | |
---|
1254 | case GCONF_VALUE_STRING: |
---|
1255 | gconf_value_set_string(val, *((const gchar**)address)); |
---|
1256 | break; |
---|
1257 | |
---|
1258 | case GCONF_VALUE_FLOAT: |
---|
1259 | gconf_value_set_float(val, *((const gdouble*)address)); |
---|
1260 | break; |
---|
1261 | |
---|
1262 | case GCONF_VALUE_SCHEMA: |
---|
1263 | gconf_value_set_schema(val, *((GConfSchema**)address)); |
---|
1264 | break; |
---|
1265 | |
---|
1266 | default: |
---|
1267 | g_assert_not_reached(); |
---|
1268 | break; |
---|
1269 | } |
---|
1270 | |
---|
1271 | return val; |
---|
1272 | } |
---|
1273 | |
---|
1274 | GConfValue* |
---|
1275 | gconf_value_pair_from_primitive_pair(GConfValueType car_type, |
---|
1276 | GConfValueType cdr_type, |
---|
1277 | gconstpointer address_of_car, |
---|
1278 | gconstpointer address_of_cdr) |
---|
1279 | { |
---|
1280 | GConfValue* pair; |
---|
1281 | GConfValue* car; |
---|
1282 | GConfValue* cdr; |
---|
1283 | |
---|
1284 | g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, NULL); |
---|
1285 | g_return_val_if_fail(car_type != GCONF_VALUE_LIST, NULL); |
---|
1286 | g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, NULL); |
---|
1287 | g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, NULL); |
---|
1288 | g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, NULL); |
---|
1289 | g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, NULL); |
---|
1290 | g_return_val_if_fail(address_of_car != NULL, NULL); |
---|
1291 | g_return_val_if_fail(address_of_cdr != NULL, NULL); |
---|
1292 | |
---|
1293 | car = from_primitive(car_type, address_of_car); |
---|
1294 | cdr = from_primitive(cdr_type, address_of_cdr); |
---|
1295 | |
---|
1296 | pair = gconf_value_new(GCONF_VALUE_PAIR); |
---|
1297 | gconf_value_set_car_nocopy(pair, car); |
---|
1298 | gconf_value_set_cdr_nocopy(pair, cdr); |
---|
1299 | |
---|
1300 | return pair; |
---|
1301 | } |
---|
1302 | |
---|
1303 | |
---|
1304 | GSList* |
---|
1305 | gconf_value_list_to_primitive_list_destructive(GConfValue* val, |
---|
1306 | GConfValueType list_type, |
---|
1307 | GError** err) |
---|
1308 | { |
---|
1309 | GSList* retval; |
---|
1310 | |
---|
1311 | g_return_val_if_fail(val != NULL, NULL); |
---|
1312 | g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL); |
---|
1313 | g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL); |
---|
1314 | g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL); |
---|
1315 | g_return_val_if_fail(err == NULL || *err == NULL, NULL); |
---|
1316 | |
---|
1317 | if (val->type != GCONF_VALUE_LIST) |
---|
1318 | { |
---|
1319 | if (err) |
---|
1320 | *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, |
---|
1321 | _("Expected list, got %s"), |
---|
1322 | gconf_value_type_to_string(val->type)); |
---|
1323 | gconf_value_free(val); |
---|
1324 | return NULL; |
---|
1325 | } |
---|
1326 | |
---|
1327 | if (gconf_value_get_list_type(val) != list_type) |
---|
1328 | { |
---|
1329 | if (err) |
---|
1330 | *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, |
---|
1331 | _("Expected list of %s, got list of %s"), |
---|
1332 | gconf_value_type_to_string(list_type), |
---|
1333 | gconf_value_type_to_string(val->type)); |
---|
1334 | gconf_value_free(val); |
---|
1335 | return NULL; |
---|
1336 | } |
---|
1337 | |
---|
1338 | g_assert(gconf_value_get_list_type(val) == list_type); |
---|
1339 | |
---|
1340 | retval = gconf_value_get_list(val); |
---|
1341 | |
---|
1342 | /* Cheating the API to avoid a list copy; set this to NULL to |
---|
1343 | avoid destroying the list */ |
---|
1344 | val->d.list_data.list = NULL; |
---|
1345 | |
---|
1346 | gconf_value_free(val); |
---|
1347 | val = NULL; |
---|
1348 | |
---|
1349 | { |
---|
1350 | /* map (typeChange, retval) */ |
---|
1351 | GSList* tmp; |
---|
1352 | |
---|
1353 | tmp = retval; |
---|
1354 | |
---|
1355 | while (tmp != NULL) |
---|
1356 | { |
---|
1357 | GConfValue* elem = tmp->data; |
---|
1358 | |
---|
1359 | g_assert(elem != NULL); |
---|
1360 | g_assert(elem->type == list_type); |
---|
1361 | |
---|
1362 | switch (list_type) |
---|
1363 | { |
---|
1364 | case GCONF_VALUE_INT: |
---|
1365 | case GCONF_VALUE_BOOL: |
---|
1366 | tmp->data = GINT_TO_POINTER(gconf_value_get_int(elem)); |
---|
1367 | break; |
---|
1368 | |
---|
1369 | case GCONF_VALUE_FLOAT: |
---|
1370 | { |
---|
1371 | gdouble* d = g_new(gdouble, 1); |
---|
1372 | *d = gconf_value_get_float(elem); |
---|
1373 | tmp->data = d; |
---|
1374 | } |
---|
1375 | break; |
---|
1376 | |
---|
1377 | case GCONF_VALUE_STRING: |
---|
1378 | { |
---|
1379 | /* Cheat again, and steal the string from the value */ |
---|
1380 | tmp->data = elem->d.string_data; |
---|
1381 | elem->d.string_data = NULL; |
---|
1382 | } |
---|
1383 | break; |
---|
1384 | |
---|
1385 | case GCONF_VALUE_SCHEMA: |
---|
1386 | { |
---|
1387 | /* and also steal the schema... */ |
---|
1388 | tmp->data = elem->d.schema_data; |
---|
1389 | elem->d.schema_data = NULL; |
---|
1390 | } |
---|
1391 | break; |
---|
1392 | |
---|
1393 | default: |
---|
1394 | g_assert_not_reached(); |
---|
1395 | break; |
---|
1396 | } |
---|
1397 | |
---|
1398 | /* Clean up the value */ |
---|
1399 | gconf_value_free(elem); |
---|
1400 | |
---|
1401 | tmp = g_slist_next(tmp); |
---|
1402 | } |
---|
1403 | } /* list conversion block */ |
---|
1404 | |
---|
1405 | return retval; |
---|
1406 | } |
---|
1407 | |
---|
1408 | |
---|
1409 | static void |
---|
1410 | primitive_value(gpointer retloc, GConfValue* val) |
---|
1411 | { |
---|
1412 | switch (val->type) |
---|
1413 | { |
---|
1414 | case GCONF_VALUE_INT: |
---|
1415 | *((gint*)retloc) = gconf_value_get_int(val); |
---|
1416 | break; |
---|
1417 | |
---|
1418 | case GCONF_VALUE_FLOAT: |
---|
1419 | *((gdouble*)retloc) = gconf_value_get_float(val); |
---|
1420 | break; |
---|
1421 | |
---|
1422 | case GCONF_VALUE_STRING: |
---|
1423 | { |
---|
1424 | *((gchar**)retloc) = val->d.string_data; |
---|
1425 | /* cheat and steal the string to avoid a copy */ |
---|
1426 | val->d.string_data = NULL; |
---|
1427 | } |
---|
1428 | break; |
---|
1429 | |
---|
1430 | case GCONF_VALUE_BOOL: |
---|
1431 | *((gboolean*)retloc) = gconf_value_get_bool(val); |
---|
1432 | break; |
---|
1433 | |
---|
1434 | case GCONF_VALUE_SCHEMA: |
---|
1435 | *((GConfSchema**)retloc) = gconf_value_get_schema(val); |
---|
1436 | break; |
---|
1437 | |
---|
1438 | default: |
---|
1439 | g_assert_not_reached(); |
---|
1440 | break; |
---|
1441 | } |
---|
1442 | } |
---|
1443 | |
---|
1444 | gboolean |
---|
1445 | gconf_value_pair_to_primitive_pair_destructive(GConfValue* val, |
---|
1446 | GConfValueType car_type, |
---|
1447 | GConfValueType cdr_type, |
---|
1448 | gpointer car_retloc, |
---|
1449 | gpointer cdr_retloc, |
---|
1450 | GError** err) |
---|
1451 | { |
---|
1452 | GConfValue* car; |
---|
1453 | GConfValue* cdr; |
---|
1454 | |
---|
1455 | g_return_val_if_fail(val != NULL, FALSE); |
---|
1456 | g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE); |
---|
1457 | g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE); |
---|
1458 | g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE); |
---|
1459 | g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE); |
---|
1460 | g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE); |
---|
1461 | g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE); |
---|
1462 | g_return_val_if_fail(car_retloc != NULL, FALSE); |
---|
1463 | g_return_val_if_fail(cdr_retloc != NULL, FALSE); |
---|
1464 | g_return_val_if_fail(err == NULL || *err == NULL, FALSE); |
---|
1465 | |
---|
1466 | if (val->type != GCONF_VALUE_PAIR) |
---|
1467 | { |
---|
1468 | if (err) |
---|
1469 | *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, |
---|
1470 | _("Expected pair, got %s"), |
---|
1471 | gconf_value_type_to_string(val->type)); |
---|
1472 | gconf_value_free(val); |
---|
1473 | return FALSE; |
---|
1474 | } |
---|
1475 | |
---|
1476 | car = gconf_value_get_car(val); |
---|
1477 | cdr = gconf_value_get_cdr(val); |
---|
1478 | |
---|
1479 | if (car == NULL || |
---|
1480 | cdr == NULL) |
---|
1481 | { |
---|
1482 | if (err) |
---|
1483 | *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, |
---|
1484 | _("Expected (%s,%s) pair, got a pair with one or both values missing"), |
---|
1485 | gconf_value_type_to_string(car_type), |
---|
1486 | gconf_value_type_to_string(cdr_type)); |
---|
1487 | |
---|
1488 | gconf_value_free(val); |
---|
1489 | return FALSE; |
---|
1490 | } |
---|
1491 | |
---|
1492 | g_assert(car != NULL); |
---|
1493 | g_assert(cdr != NULL); |
---|
1494 | |
---|
1495 | if (car->type != car_type || |
---|
1496 | cdr->type != cdr_type) |
---|
1497 | { |
---|
1498 | if (err) |
---|
1499 | *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, |
---|
1500 | _("Expected pair of type (%s,%s) got type (%s,%s)"), |
---|
1501 | gconf_value_type_to_string(car_type), |
---|
1502 | gconf_value_type_to_string(cdr_type), |
---|
1503 | gconf_value_type_to_string(car->type), |
---|
1504 | gconf_value_type_to_string(cdr->type)); |
---|
1505 | gconf_value_free(val); |
---|
1506 | return FALSE; |
---|
1507 | } |
---|
1508 | |
---|
1509 | primitive_value(car_retloc, car); |
---|
1510 | primitive_value(cdr_retloc, cdr); |
---|
1511 | |
---|
1512 | gconf_value_free(val); |
---|
1513 | |
---|
1514 | return TRUE; |
---|
1515 | } |
---|
1516 | |
---|
1517 | |
---|
1518 | |
---|
1519 | /* |
---|
1520 | * Encode/decode |
---|
1521 | */ |
---|
1522 | |
---|
1523 | gchar* |
---|
1524 | gconf_quote_string (const gchar* src) |
---|
1525 | { |
---|
1526 | gchar* dest; |
---|
1527 | const gchar* s; |
---|
1528 | gchar* d; |
---|
1529 | |
---|
1530 | g_return_val_if_fail(src != NULL, NULL); |
---|
1531 | |
---|
1532 | /* waste memory! woo-hoo! */ |
---|
1533 | dest = g_malloc0(strlen(src)*2+4); |
---|
1534 | |
---|
1535 | d = dest; |
---|
1536 | |
---|
1537 | *d = '"'; |
---|
1538 | ++d; |
---|
1539 | |
---|
1540 | s = src; |
---|
1541 | while (*s) |
---|
1542 | { |
---|
1543 | switch (*s) |
---|
1544 | { |
---|
1545 | case '"': |
---|
1546 | { |
---|
1547 | *d = '\\'; |
---|
1548 | ++d; |
---|
1549 | *d = '"'; |
---|
1550 | ++d; |
---|
1551 | } |
---|
1552 | break; |
---|
1553 | |
---|
1554 | case '\\': |
---|
1555 | { |
---|
1556 | *d = '\\'; |
---|
1557 | ++d; |
---|
1558 | *d = '\\'; |
---|
1559 | ++d; |
---|
1560 | } |
---|
1561 | break; |
---|
1562 | |
---|
1563 | default: |
---|
1564 | { |
---|
1565 | *d = *s; |
---|
1566 | ++d; |
---|
1567 | } |
---|
1568 | break; |
---|
1569 | } |
---|
1570 | ++s; |
---|
1571 | } |
---|
1572 | |
---|
1573 | /* End with quote mark and NULL */ |
---|
1574 | *d = '"'; |
---|
1575 | ++d; |
---|
1576 | *d = '\0'; |
---|
1577 | |
---|
1578 | return dest; |
---|
1579 | } |
---|
1580 | |
---|
1581 | gchar* |
---|
1582 | gconf_unquote_string (const gchar* str, const gchar** end, GError** err) |
---|
1583 | { |
---|
1584 | gchar* unq; |
---|
1585 | gchar* unq_end = NULL; |
---|
1586 | |
---|
1587 | g_return_val_if_fail(end != NULL, NULL); |
---|
1588 | g_return_val_if_fail(err == NULL || *err == NULL, NULL); |
---|
1589 | g_return_val_if_fail(str != NULL, NULL); |
---|
1590 | |
---|
1591 | unq = g_strdup(str); |
---|
1592 | |
---|
1593 | gconf_unquote_string_inplace(unq, &unq_end, err); |
---|
1594 | |
---|
1595 | *end = (str + (unq_end - unq)); |
---|
1596 | |
---|
1597 | return unq; |
---|
1598 | } |
---|
1599 | |
---|
1600 | void |
---|
1601 | gconf_unquote_string_inplace (gchar* str, gchar** end, GError** err) |
---|
1602 | { |
---|
1603 | gchar* dest; |
---|
1604 | gchar* s; |
---|
1605 | |
---|
1606 | g_return_if_fail(end != NULL); |
---|
1607 | g_return_if_fail(err == NULL || *err == NULL); |
---|
1608 | g_return_if_fail(str != NULL); |
---|
1609 | |
---|
1610 | dest = s = str; |
---|
1611 | |
---|
1612 | if (*s != '"') |
---|
1613 | { |
---|
1614 | if (err) |
---|
1615 | *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR, |
---|
1616 | _("Quoted string doesn't begin with a quotation mark")); |
---|
1617 | *end = str; |
---|
1618 | return; |
---|
1619 | } |
---|
1620 | |
---|
1621 | /* Skip the initial quote mark */ |
---|
1622 | ++s; |
---|
1623 | |
---|
1624 | while (*s) |
---|
1625 | { |
---|
1626 | g_assert(s > dest); /* loop invariant */ |
---|
1627 | |
---|
1628 | switch (*s) |
---|
1629 | { |
---|
1630 | case '"': |
---|
1631 | /* End of the string, return now */ |
---|
1632 | *dest = '\0'; |
---|
1633 | ++s; |
---|
1634 | *end = s; |
---|
1635 | return; |
---|
1636 | break; |
---|
1637 | |
---|
1638 | case '\\': |
---|
1639 | /* Possible escaped quote or \ */ |
---|
1640 | ++s; |
---|
1641 | if (*s == '"') |
---|
1642 | { |
---|
1643 | *dest = *s; |
---|
1644 | ++s; |
---|
1645 | ++dest; |
---|
1646 | } |
---|
1647 | else if (*s == '\\') |
---|
1648 | { |
---|
1649 | *dest = *s; |
---|
1650 | ++s; |
---|
1651 | ++dest; |
---|
1652 | } |
---|
1653 | else |
---|
1654 | { |
---|
1655 | /* not an escaped char */ |
---|
1656 | *dest = '\\'; |
---|
1657 | ++dest; |
---|
1658 | /* ++s already done. */ |
---|
1659 | } |
---|
1660 | break; |
---|
1661 | |
---|
1662 | default: |
---|
1663 | *dest = *s; |
---|
1664 | ++dest; |
---|
1665 | ++s; |
---|
1666 | break; |
---|
1667 | } |
---|
1668 | |
---|
1669 | g_assert(s > dest); /* loop invariant */ |
---|
1670 | } |
---|
1671 | |
---|
1672 | /* If we reach here this means the close quote was never encountered */ |
---|
1673 | |
---|
1674 | *dest = '\0'; |
---|
1675 | |
---|
1676 | if (err) |
---|
1677 | *err = gconf_error_new(GCONF_ERROR_PARSE_ERROR, |
---|
1678 | _("Quoted string doesn't end with a quotation mark")); |
---|
1679 | *end = s; |
---|
1680 | return; |
---|
1681 | } |
---|
1682 | |
---|
1683 | /* The encoding format |
---|
1684 | |
---|
1685 | The first byte of the encoded string is the type of the value: |
---|
1686 | |
---|
1687 | i int |
---|
1688 | b bool |
---|
1689 | f float |
---|
1690 | s string |
---|
1691 | c schema |
---|
1692 | p pair |
---|
1693 | l list |
---|
1694 | v invalid |
---|
1695 | |
---|
1696 | For int, the rest of the encoded value is the integer to be parsed with atoi() |
---|
1697 | For bool, the rest is 't' or 'f' |
---|
1698 | For float, the rest is a float to parse with g_strtod() |
---|
1699 | For string, the rest is the string (not quoted) |
---|
1700 | For schema, the encoding is complicated; see below. |
---|
1701 | For pair, the rest is two primitive encodings (ibcfs), quoted, separated by a comma, |
---|
1702 | car before cdr |
---|
1703 | For list, first character is type, the rest is primitive encodings, quoted, |
---|
1704 | separated by commas |
---|
1705 | |
---|
1706 | Schema: |
---|
1707 | |
---|
1708 | After the 'c' indicating schema, the second character is a byte indicating |
---|
1709 | the type the schema expects. Then a comma, and the quoted locale, or "" for none. |
---|
1710 | comma, and quoted short description; comma, quoted long description; comma, default |
---|
1711 | value in the encoded format given above, quoted. |
---|
1712 | */ |
---|
1713 | |
---|
1714 | static gchar type_byte(GConfValueType type) |
---|
1715 | { |
---|
1716 | switch (type) |
---|
1717 | { |
---|
1718 | case GCONF_VALUE_INT: |
---|
1719 | return 'i'; |
---|
1720 | break; |
---|
1721 | |
---|
1722 | case GCONF_VALUE_BOOL: |
---|
1723 | return 'b'; |
---|
1724 | break; |
---|
1725 | |
---|
1726 | case GCONF_VALUE_FLOAT: |
---|
1727 | return 'f'; |
---|
1728 | break; |
---|
1729 | |
---|
1730 | case GCONF_VALUE_STRING: |
---|
1731 | return 's'; |
---|
1732 | break; |
---|
1733 | |
---|
1734 | case GCONF_VALUE_SCHEMA: |
---|
1735 | return 'c'; |
---|
1736 | break; |
---|
1737 | |
---|
1738 | case GCONF_VALUE_LIST: |
---|
1739 | return 'l'; |
---|
1740 | break; |
---|
1741 | |
---|
1742 | case GCONF_VALUE_PAIR: |
---|
1743 | return 'p'; |
---|
1744 | break; |
---|
1745 | |
---|
1746 | case GCONF_VALUE_INVALID: |
---|
1747 | return 'v'; |
---|
1748 | break; |
---|
1749 | |
---|
1750 | default: |
---|
1751 | g_assert_not_reached(); |
---|
1752 | return '\0'; |
---|
1753 | break; |
---|
1754 | } |
---|
1755 | } |
---|
1756 | |
---|
1757 | GConfValueType |
---|
1758 | byte_type(gchar byte) |
---|
1759 | { |
---|
1760 | switch (byte) |
---|
1761 | { |
---|
1762 | case 'i': |
---|
1763 | return GCONF_VALUE_INT; |
---|
1764 | break; |
---|
1765 | |
---|
1766 | case 'b': |
---|
1767 | return GCONF_VALUE_BOOL; |
---|
1768 | break; |
---|
1769 | |
---|
1770 | case 's': |
---|
1771 | return GCONF_VALUE_STRING; |
---|
1772 | break; |
---|
1773 | |
---|
1774 | case 'c': |
---|
1775 | return GCONF_VALUE_SCHEMA; |
---|
1776 | break; |
---|
1777 | |
---|
1778 | case 'f': |
---|
1779 | return GCONF_VALUE_FLOAT; |
---|
1780 | break; |
---|
1781 | |
---|
1782 | case 'l': |
---|
1783 | return GCONF_VALUE_LIST; |
---|
1784 | break; |
---|
1785 | |
---|
1786 | case 'p': |
---|
1787 | return GCONF_VALUE_PAIR; |
---|
1788 | break; |
---|
1789 | |
---|
1790 | case 'v': |
---|
1791 | return GCONF_VALUE_INVALID; |
---|
1792 | break; |
---|
1793 | |
---|
1794 | default: |
---|
1795 | return GCONF_VALUE_INVALID; |
---|
1796 | break; |
---|
1797 | } |
---|
1798 | } |
---|
1799 | |
---|
1800 | GConfValue* |
---|
1801 | gconf_value_decode (const gchar* encoded) |
---|
1802 | { |
---|
1803 | GConfValueType type; |
---|
1804 | GConfValue* val; |
---|
1805 | const gchar* s; |
---|
1806 | |
---|
1807 | type = byte_type(*encoded); |
---|
1808 | |
---|
1809 | if (type == GCONF_VALUE_INVALID) |
---|
1810 | return NULL; |
---|
1811 | |
---|
1812 | val = gconf_value_new(type); |
---|
1813 | |
---|
1814 | s = encoded + 1; |
---|
1815 | |
---|
1816 | switch (val->type) |
---|
1817 | { |
---|
1818 | case GCONF_VALUE_INT: |
---|
1819 | gconf_value_set_int(val, atoi(s)); |
---|
1820 | break; |
---|
1821 | |
---|
1822 | case GCONF_VALUE_BOOL: |
---|
1823 | gconf_value_set_bool(val, *s == 't' ? TRUE : FALSE); |
---|
1824 | break; |
---|
1825 | |
---|
1826 | case GCONF_VALUE_FLOAT: |
---|
1827 | { |
---|
1828 | double d; |
---|
1829 | gchar* endptr = NULL; |
---|
1830 | |
---|
1831 | d = g_strtod(s, &endptr); |
---|
1832 | if (endptr == s) |
---|
1833 | g_warning("Failure converting string to double in %s", G_GNUC_FUNCTION); |
---|
1834 | gconf_value_set_float(val, d); |
---|
1835 | } |
---|
1836 | break; |
---|
1837 | |
---|
1838 | case GCONF_VALUE_STRING: |
---|
1839 | { |
---|
1840 | gconf_value_set_string(val, s); |
---|
1841 | } |
---|
1842 | break; |
---|
1843 | |
---|
1844 | case GCONF_VALUE_SCHEMA: |
---|
1845 | { |
---|
1846 | GConfSchema* sc = gconf_schema_new(); |
---|
1847 | const gchar* end = NULL; |
---|
1848 | gchar* unquoted; |
---|
1849 | |
---|
1850 | gconf_value_set_schema(val, sc); |
---|
1851 | |
---|
1852 | gconf_schema_set_type(sc, byte_type(*s)); |
---|
1853 | ++s; |
---|
1854 | gconf_schema_set_list_type(sc, byte_type(*s)); |
---|
1855 | ++s; |
---|
1856 | gconf_schema_set_car_type(sc, byte_type(*s)); |
---|
1857 | ++s; |
---|
1858 | gconf_schema_set_cdr_type(sc, byte_type(*s)); |
---|
1859 | ++s; |
---|
1860 | |
---|
1861 | /* locale */ |
---|
1862 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1863 | |
---|
1864 | gconf_schema_set_locale(sc, unquoted); |
---|
1865 | |
---|
1866 | g_free(unquoted); |
---|
1867 | |
---|
1868 | if (*end != ',') |
---|
1869 | g_warning("no comma after locale in schema"); |
---|
1870 | |
---|
1871 | ++end; |
---|
1872 | s = end; |
---|
1873 | |
---|
1874 | /* short */ |
---|
1875 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1876 | |
---|
1877 | gconf_schema_set_short_desc(sc, unquoted); |
---|
1878 | |
---|
1879 | g_free(unquoted); |
---|
1880 | |
---|
1881 | if (*end != ',') |
---|
1882 | g_warning("no comma after short desc in schema"); |
---|
1883 | |
---|
1884 | ++end; |
---|
1885 | s = end; |
---|
1886 | |
---|
1887 | |
---|
1888 | /* long */ |
---|
1889 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1890 | |
---|
1891 | gconf_schema_set_long_desc(sc, unquoted); |
---|
1892 | |
---|
1893 | g_free(unquoted); |
---|
1894 | |
---|
1895 | if (*end != ',') |
---|
1896 | g_warning("no comma after long desc in schema"); |
---|
1897 | |
---|
1898 | ++end; |
---|
1899 | s = end; |
---|
1900 | |
---|
1901 | |
---|
1902 | /* default value */ |
---|
1903 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1904 | |
---|
1905 | gconf_schema_set_default_value_nocopy(sc, gconf_value_decode(unquoted)); |
---|
1906 | |
---|
1907 | g_free(unquoted); |
---|
1908 | |
---|
1909 | if (*end != '\0') |
---|
1910 | g_warning("trailing junk after encoded schema"); |
---|
1911 | } |
---|
1912 | break; |
---|
1913 | |
---|
1914 | case GCONF_VALUE_LIST: |
---|
1915 | { |
---|
1916 | GSList* value_list = NULL; |
---|
1917 | |
---|
1918 | gconf_value_set_list_type(val, byte_type(*s)); |
---|
1919 | ++s; |
---|
1920 | |
---|
1921 | while (*s) |
---|
1922 | { |
---|
1923 | gchar* unquoted; |
---|
1924 | const gchar* end; |
---|
1925 | |
---|
1926 | GConfValue* elem; |
---|
1927 | |
---|
1928 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1929 | |
---|
1930 | elem = gconf_value_decode(unquoted); |
---|
1931 | |
---|
1932 | g_free(unquoted); |
---|
1933 | |
---|
1934 | if (elem) |
---|
1935 | value_list = g_slist_prepend(value_list, elem); |
---|
1936 | |
---|
1937 | s = end; |
---|
1938 | if (*s == ',') |
---|
1939 | ++s; |
---|
1940 | else if (*s != '\0') |
---|
1941 | { |
---|
1942 | g_warning("weird character in encoded list"); |
---|
1943 | break; /* error */ |
---|
1944 | } |
---|
1945 | } |
---|
1946 | |
---|
1947 | value_list = g_slist_reverse(value_list); |
---|
1948 | |
---|
1949 | gconf_value_set_list_nocopy(val, value_list); |
---|
1950 | } |
---|
1951 | break; |
---|
1952 | |
---|
1953 | case GCONF_VALUE_PAIR: |
---|
1954 | { |
---|
1955 | gchar* unquoted; |
---|
1956 | const gchar* end; |
---|
1957 | |
---|
1958 | GConfValue* car; |
---|
1959 | GConfValue* cdr; |
---|
1960 | |
---|
1961 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1962 | |
---|
1963 | car = gconf_value_decode(unquoted); |
---|
1964 | |
---|
1965 | g_free(unquoted); |
---|
1966 | |
---|
1967 | s = end; |
---|
1968 | if (*s == ',') |
---|
1969 | ++s; |
---|
1970 | else |
---|
1971 | { |
---|
1972 | g_warning("weird character in encoded pair"); |
---|
1973 | } |
---|
1974 | |
---|
1975 | unquoted = gconf_unquote_string(s, &end, NULL); |
---|
1976 | |
---|
1977 | cdr = gconf_value_decode(unquoted); |
---|
1978 | g_free(unquoted); |
---|
1979 | |
---|
1980 | |
---|
1981 | gconf_value_set_car_nocopy(val, car); |
---|
1982 | gconf_value_set_cdr_nocopy(val, cdr); |
---|
1983 | } |
---|
1984 | break; |
---|
1985 | |
---|
1986 | default: |
---|
1987 | g_assert_not_reached(); |
---|
1988 | break; |
---|
1989 | } |
---|
1990 | |
---|
1991 | return val; |
---|
1992 | } |
---|
1993 | |
---|
1994 | gchar* |
---|
1995 | gconf_value_encode (GConfValue* val) |
---|
1996 | { |
---|
1997 | gchar* retval = NULL; |
---|
1998 | |
---|
1999 | g_return_val_if_fail(val != NULL, NULL); |
---|
2000 | |
---|
2001 | switch (val->type) |
---|
2002 | { |
---|
2003 | case GCONF_VALUE_INT: |
---|
2004 | retval = g_strdup_printf("i%d", gconf_value_get_int(val)); |
---|
2005 | break; |
---|
2006 | |
---|
2007 | case GCONF_VALUE_BOOL: |
---|
2008 | retval = g_strdup_printf("b%c", gconf_value_get_bool(val) ? 't' : 'f'); |
---|
2009 | break; |
---|
2010 | |
---|
2011 | case GCONF_VALUE_FLOAT: |
---|
2012 | retval = g_strdup_printf("f%g", gconf_value_get_float(val)); |
---|
2013 | break; |
---|
2014 | |
---|
2015 | case GCONF_VALUE_STRING: |
---|
2016 | retval = g_strdup_printf("s%s", gconf_value_get_string(val)); |
---|
2017 | break; |
---|
2018 | |
---|
2019 | case GCONF_VALUE_SCHEMA: |
---|
2020 | { |
---|
2021 | gchar* tmp; |
---|
2022 | gchar* retval; |
---|
2023 | gchar* quoted; |
---|
2024 | gchar* encoded; |
---|
2025 | GConfSchema* sc; |
---|
2026 | |
---|
2027 | sc = gconf_value_get_schema(val); |
---|
2028 | |
---|
2029 | tmp = g_strdup_printf("c%c%c%c%c,", |
---|
2030 | type_byte(gconf_schema_get_type(sc)), |
---|
2031 | type_byte(gconf_schema_get_list_type(sc)), |
---|
2032 | type_byte(gconf_schema_get_car_type(sc)), |
---|
2033 | type_byte(gconf_schema_get_cdr_type(sc))); |
---|
2034 | |
---|
2035 | quoted = gconf_quote_string(gconf_schema_get_locale(sc) ? |
---|
2036 | gconf_schema_get_locale(sc) : ""); |
---|
2037 | retval = g_strconcat(tmp, quoted, ",", NULL); |
---|
2038 | |
---|
2039 | g_free(tmp); |
---|
2040 | g_free(quoted); |
---|
2041 | |
---|
2042 | tmp = retval; |
---|
2043 | quoted = gconf_quote_string(gconf_schema_get_short_desc(sc) ? |
---|
2044 | gconf_schema_get_short_desc(sc) : ""); |
---|
2045 | |
---|
2046 | retval = g_strconcat(tmp, quoted, ",", NULL); |
---|
2047 | |
---|
2048 | g_free(tmp); |
---|
2049 | g_free(quoted); |
---|
2050 | |
---|
2051 | |
---|
2052 | tmp = retval; |
---|
2053 | quoted = gconf_quote_string(gconf_schema_get_long_desc(sc) ? |
---|
2054 | gconf_schema_get_long_desc(sc) : ""); |
---|
2055 | |
---|
2056 | retval = g_strconcat(tmp, quoted, ",", NULL); |
---|
2057 | |
---|
2058 | g_free(tmp); |
---|
2059 | g_free(quoted); |
---|
2060 | |
---|
2061 | |
---|
2062 | if (gconf_schema_get_default_value(sc) != NULL) |
---|
2063 | encoded = gconf_value_encode(gconf_schema_get_default_value(sc)); |
---|
2064 | else |
---|
2065 | encoded = g_strdup(""); |
---|
2066 | |
---|
2067 | tmp = retval; |
---|
2068 | |
---|
2069 | quoted = gconf_quote_string(encoded); |
---|
2070 | |
---|
2071 | retval = g_strconcat(tmp, quoted, NULL); |
---|
2072 | |
---|
2073 | g_free(tmp); |
---|
2074 | g_free(quoted); |
---|
2075 | g_free(encoded); |
---|
2076 | } |
---|
2077 | break; |
---|
2078 | |
---|
2079 | case GCONF_VALUE_LIST: |
---|
2080 | { |
---|
2081 | GSList* tmp; |
---|
2082 | |
---|
2083 | retval = g_strdup_printf("l%c", type_byte(gconf_value_get_list_type(val))); |
---|
2084 | |
---|
2085 | tmp = gconf_value_get_list(val); |
---|
2086 | |
---|
2087 | while (tmp != NULL) |
---|
2088 | { |
---|
2089 | GConfValue* elem = tmp->data; |
---|
2090 | gchar* encoded; |
---|
2091 | gchar* quoted; |
---|
2092 | |
---|
2093 | g_assert(elem != NULL); |
---|
2094 | |
---|
2095 | encoded = gconf_value_encode(elem); |
---|
2096 | |
---|
2097 | quoted = gconf_quote_string(encoded); |
---|
2098 | |
---|
2099 | g_free(encoded); |
---|
2100 | |
---|
2101 | { |
---|
2102 | gchar* free_me; |
---|
2103 | free_me = retval; |
---|
2104 | |
---|
2105 | retval = g_strconcat(retval, ",", quoted, NULL); |
---|
2106 | |
---|
2107 | g_free(quoted); |
---|
2108 | g_free(free_me); |
---|
2109 | } |
---|
2110 | |
---|
2111 | tmp = g_slist_next(tmp); |
---|
2112 | } |
---|
2113 | } |
---|
2114 | break; |
---|
2115 | |
---|
2116 | case GCONF_VALUE_PAIR: |
---|
2117 | { |
---|
2118 | gchar* car_encoded; |
---|
2119 | gchar* cdr_encoded; |
---|
2120 | gchar* car_quoted; |
---|
2121 | gchar* cdr_quoted; |
---|
2122 | |
---|
2123 | car_encoded = gconf_value_encode(gconf_value_get_car(val)); |
---|
2124 | cdr_encoded = gconf_value_encode(gconf_value_get_cdr(val)); |
---|
2125 | |
---|
2126 | car_quoted = gconf_quote_string(car_encoded); |
---|
2127 | cdr_quoted = gconf_quote_string(cdr_encoded); |
---|
2128 | |
---|
2129 | retval = g_strconcat("p", car_quoted, ",", cdr_quoted, NULL); |
---|
2130 | |
---|
2131 | g_free(car_encoded); |
---|
2132 | g_free(cdr_encoded); |
---|
2133 | g_free(car_quoted); |
---|
2134 | g_free(cdr_quoted); |
---|
2135 | } |
---|
2136 | break; |
---|
2137 | |
---|
2138 | default: |
---|
2139 | g_assert_not_reached(); |
---|
2140 | break; |
---|
2141 | |
---|
2142 | } |
---|
2143 | |
---|
2144 | return retval; |
---|
2145 | } |
---|
2146 | |
---|
2147 | gboolean |
---|
2148 | gconf_handle_oaf_exception(CORBA_Environment* ev, GError** err) |
---|
2149 | { |
---|
2150 | switch (ev->_major) |
---|
2151 | { |
---|
2152 | case CORBA_NO_EXCEPTION: |
---|
2153 | CORBA_exception_free(ev); |
---|
2154 | return FALSE; |
---|
2155 | break; |
---|
2156 | case CORBA_SYSTEM_EXCEPTION: |
---|
2157 | if (err) |
---|
2158 | *err = gconf_error_new(GCONF_ERROR_NO_SERVER, _("CORBA error: %s"), |
---|
2159 | CORBA_exception_id(ev)); |
---|
2160 | CORBA_exception_free(ev); |
---|
2161 | return TRUE; |
---|
2162 | break; |
---|
2163 | |
---|
2164 | case CORBA_USER_EXCEPTION: |
---|
2165 | { |
---|
2166 | const gchar* id = CORBA_exception_id(ev); |
---|
2167 | |
---|
2168 | if (strcmp(id, "IDL:OAF/GeneralError:1.0") == 0) |
---|
2169 | { |
---|
2170 | OAF_GeneralError* ge = CORBA_exception_value(ev); |
---|
2171 | |
---|
2172 | if (err) |
---|
2173 | *err = gconf_error_new(GCONF_ERROR_OAF_ERROR, |
---|
2174 | _("OAF problem description: '%s'"), |
---|
2175 | ge->description); |
---|
2176 | } |
---|
2177 | else if (strcmp(id,"IDL:OAF/ActivationContext/NotListed:1.0" ) == 0) |
---|
2178 | { |
---|
2179 | if (err) |
---|
2180 | *err = gconf_error_new(GCONF_ERROR_OAF_ERROR, _("attempt to remove not-listed OAF object directory")); |
---|
2181 | } |
---|
2182 | else if (strcmp(id,"IDL:OAF/ActivationContext/AlreadyListed:1.0" ) == 0) |
---|
2183 | { |
---|
2184 | if (err) |
---|
2185 | *err = gconf_error_new(GCONF_ERROR_OAF_ERROR, _("attempt to add already-listed OAF directory")); |
---|
2186 | } |
---|
2187 | else if (strcmp(id,"IDL:OAF/ActivationContext/ParseFailed:1.0") == 0) |
---|
2188 | { |
---|
2189 | OAF_ActivationContext_ParseFailed* pe = CORBA_exception_value(ev); |
---|
2190 | |
---|
2191 | if (err) |
---|
2192 | *err = gconf_error_new(GCONF_ERROR_OAF_ERROR, _("OAF parse error: %s"), pe->description); |
---|
2193 | } |
---|
2194 | else |
---|
2195 | { |
---|
2196 | if (err) |
---|
2197 | *err = gconf_error_new(GCONF_ERROR_OAF_ERROR, _("Unknown OAF error")); |
---|
2198 | } |
---|
2199 | |
---|
2200 | CORBA_exception_free(ev); |
---|
2201 | return TRUE; |
---|
2202 | } |
---|
2203 | break; |
---|
2204 | default: |
---|
2205 | g_assert_not_reached(); |
---|
2206 | return TRUE; |
---|
2207 | break; |
---|
2208 | } |
---|
2209 | } |
---|
2210 | |
---|
2211 | /* Sleep */ |
---|
2212 | |
---|
2213 | #ifdef HAVE_NANOSLEEP |
---|
2214 | |
---|
2215 | void |
---|
2216 | gconf_nanosleep(gulong useconds) |
---|
2217 | { |
---|
2218 | struct timespec ts; |
---|
2219 | |
---|
2220 | ts.tv_sec = (long int)(useconds/1000000); |
---|
2221 | ts.tv_nsec = (long int)(useconds%1000000)*1000ul; |
---|
2222 | |
---|
2223 | nanosleep(&ts,NULL); |
---|
2224 | } |
---|
2225 | |
---|
2226 | #elif HAVE_USLEEP |
---|
2227 | |
---|
2228 | void |
---|
2229 | gconf_nanosleep(gulong useconds) |
---|
2230 | { |
---|
2231 | usleep(useconds); |
---|
2232 | } |
---|
2233 | |
---|
2234 | #else |
---|
2235 | #error "need nanosleep or usleep right now (fix with simple select() hack)" |
---|
2236 | #endif |
---|
2237 | |
---|
2238 | /* |
---|
2239 | * Locks using directories, to work on NFS (at least potentially) |
---|
2240 | */ |
---|
2241 | |
---|
2242 | struct _GConfLock { |
---|
2243 | gchar* lock_directory; |
---|
2244 | }; |
---|
2245 | |
---|
2246 | static void |
---|
2247 | gconf_lock_destroy(GConfLock* lock) |
---|
2248 | { |
---|
2249 | g_free(lock->lock_directory); |
---|
2250 | g_free(lock); |
---|
2251 | } |
---|
2252 | |
---|
2253 | GConfLock* |
---|
2254 | gconf_get_lock(const gchar* lock_directory, |
---|
2255 | GError** err) |
---|
2256 | { |
---|
2257 | GConfLock* lock; |
---|
2258 | gboolean got_it = FALSE; |
---|
2259 | gboolean error_occurred = FALSE; |
---|
2260 | gboolean stale = FALSE; |
---|
2261 | gchar* iorfile; |
---|
2262 | |
---|
2263 | g_return_val_if_fail(lock_directory != NULL, NULL); |
---|
2264 | |
---|
2265 | lock = g_new(GConfLock, 1); |
---|
2266 | |
---|
2267 | lock->lock_directory = g_strdup(lock_directory); |
---|
2268 | |
---|
2269 | iorfile = g_strconcat(lock->lock_directory, "/ior", NULL); |
---|
2270 | |
---|
2271 | if (mkdir(lock->lock_directory, 0700) < 0) |
---|
2272 | { |
---|
2273 | if (errno == EEXIST) |
---|
2274 | { |
---|
2275 | /* Check the current IOR file and ping its daemon */ |
---|
2276 | FILE* fp; |
---|
2277 | |
---|
2278 | fp = fopen(iorfile, "r"); |
---|
2279 | |
---|
2280 | if (fp == NULL) |
---|
2281 | { |
---|
2282 | gconf_log(GCL_WARNING, _("No ior file in `%s'"), |
---|
2283 | lock->lock_directory); |
---|
2284 | stale = TRUE; |
---|
2285 | got_it = TRUE; |
---|
2286 | goto out; |
---|
2287 | } |
---|
2288 | else |
---|
2289 | { |
---|
2290 | gchar buf[2048] = { '\0' }; |
---|
2291 | gchar* str = NULL; |
---|
2292 | fgets(buf, 2047, fp); |
---|
2293 | fclose(fp); |
---|
2294 | |
---|
2295 | /* The lockfile format is <pid>:<ior> for gconfd |
---|
2296 | or <pid>:none for gconftool */ |
---|
2297 | str = buf; |
---|
2298 | while (isdigit(*str)) |
---|
2299 | ++str; |
---|
2300 | |
---|
2301 | if (*str == ':') |
---|
2302 | ++str; |
---|
2303 | |
---|
2304 | if (str[0] == 'n' && |
---|
2305 | str[1] == 'o' && |
---|
2306 | str[2] == 'n' && |
---|
2307 | str[3] == 'e') |
---|
2308 | { |
---|
2309 | /* It's locked by gconftool, not a daemon; |
---|
2310 | the daemon always "wins" the lock, with a warning */ |
---|
2311 | if (gconf_in_daemon_mode()) |
---|
2312 | { |
---|
2313 | gconf_log(GCL_WARNING, _("gconfd taking lock `%s' from some other process"), |
---|
2314 | lock->lock_directory); |
---|
2315 | stale = TRUE; |
---|
2316 | got_it = TRUE; |
---|
2317 | goto out; |
---|
2318 | } |
---|
2319 | else |
---|
2320 | { |
---|
2321 | error_occurred = TRUE; |
---|
2322 | gconf_set_error(err, |
---|
2323 | GCONF_ERROR_LOCK_FAILED, |
---|
2324 | _("Another program has lock `%s'"), |
---|
2325 | lock->lock_directory); |
---|
2326 | goto out; |
---|
2327 | } |
---|
2328 | } |
---|
2329 | else |
---|
2330 | { |
---|
2331 | ConfigServer server; |
---|
2332 | CORBA_ORB orb; |
---|
2333 | CORBA_Environment ev; |
---|
2334 | |
---|
2335 | CORBA_exception_init(&ev); |
---|
2336 | |
---|
2337 | orb = oaf_orb_get(); |
---|
2338 | |
---|
2339 | if (orb == NULL) |
---|
2340 | { |
---|
2341 | error_occurred = TRUE; |
---|
2342 | gconf_set_error(err, |
---|
2343 | GCONF_ERROR_LOCK_FAILED, |
---|
2344 | _("couldn't contact ORB to ping existing gconfd")); |
---|
2345 | goto out; |
---|
2346 | } |
---|
2347 | |
---|
2348 | server = CORBA_ORB_string_to_object(orb, str, &ev); |
---|
2349 | |
---|
2350 | if (CORBA_Object_is_nil(server, &ev)) |
---|
2351 | { |
---|
2352 | gconf_log(GCL_WARNING, _("Removing stale lock `%s' because IOR couldn't be converted to object reference, IOR `%s'"), |
---|
2353 | lock->lock_directory, str); |
---|
2354 | stale = TRUE; |
---|
2355 | got_it = TRUE; |
---|
2356 | goto out; |
---|
2357 | } |
---|
2358 | else |
---|
2359 | { |
---|
2360 | ConfigServer_ping(server, &ev); |
---|
2361 | |
---|
2362 | if (ev._major != CORBA_NO_EXCEPTION) |
---|
2363 | { |
---|
2364 | gconf_log(GCL_WARNING, _("Removing stale lock `%s' because of error pinging server: %s"), |
---|
2365 | lock->lock_directory, CORBA_exception_id(&ev)); |
---|
2366 | CORBA_exception_free(&ev); |
---|
2367 | stale = TRUE; |
---|
2368 | got_it = TRUE; |
---|
2369 | goto out; |
---|
2370 | } |
---|
2371 | else |
---|
2372 | { |
---|
2373 | error_occurred = TRUE; |
---|
2374 | gconf_set_error(err, |
---|
2375 | GCONF_ERROR_LOCK_FAILED, |
---|
2376 | _("GConf configuration daemon (gconfd) has lock `%s'"), |
---|
2377 | lock->lock_directory); |
---|
2378 | goto out; |
---|
2379 | } |
---|
2380 | } |
---|
2381 | } |
---|
2382 | } |
---|
2383 | } |
---|
2384 | else |
---|
2385 | { |
---|
2386 | /* give up */ |
---|
2387 | error_occurred = TRUE; |
---|
2388 | gconf_set_error(err, |
---|
2389 | GCONF_ERROR_LOCK_FAILED, |
---|
2390 | _("couldn't create directory `%s': %s"), |
---|
2391 | lock->lock_directory, strerror(errno)); |
---|
2392 | goto out; |
---|
2393 | } |
---|
2394 | } |
---|
2395 | else |
---|
2396 | { |
---|
2397 | got_it = TRUE; |
---|
2398 | } |
---|
2399 | |
---|
2400 | out: |
---|
2401 | |
---|
2402 | if (error_occurred) |
---|
2403 | { |
---|
2404 | g_assert(!got_it); |
---|
2405 | |
---|
2406 | g_free(iorfile); |
---|
2407 | gconf_lock_destroy(lock); |
---|
2408 | return NULL; |
---|
2409 | } |
---|
2410 | |
---|
2411 | g_assert(got_it); |
---|
2412 | |
---|
2413 | if (stale) |
---|
2414 | unlink(iorfile); |
---|
2415 | |
---|
2416 | { |
---|
2417 | int fd = -1; |
---|
2418 | |
---|
2419 | fd = open(iorfile, O_WRONLY | O_CREAT | O_TRUNC, 0700); |
---|
2420 | |
---|
2421 | if (fd < 0) |
---|
2422 | { |
---|
2423 | gconf_set_error(err, |
---|
2424 | GCONF_ERROR_LOCK_FAILED, |
---|
2425 | _("Can't create lock `%s': %s"), |
---|
2426 | iorfile, strerror(errno)); |
---|
2427 | g_free(iorfile); |
---|
2428 | gconf_lock_destroy(lock); |
---|
2429 | return NULL; |
---|
2430 | } |
---|
2431 | else |
---|
2432 | { |
---|
2433 | const gchar* ior; |
---|
2434 | int retval; |
---|
2435 | gchar* s; |
---|
2436 | |
---|
2437 | s = g_strdup_printf("%u:", (guint)getpid()); |
---|
2438 | |
---|
2439 | retval = write(fd, s, strlen(s)); |
---|
2440 | |
---|
2441 | g_free(s); |
---|
2442 | |
---|
2443 | if (retval >= 0) |
---|
2444 | { |
---|
2445 | ior = gconf_get_daemon_ior(); |
---|
2446 | |
---|
2447 | if (ior == NULL) |
---|
2448 | { |
---|
2449 | retval = write(fd, "none", 4); |
---|
2450 | } |
---|
2451 | else |
---|
2452 | { |
---|
2453 | retval = write(fd, ior, strlen(ior)); |
---|
2454 | } |
---|
2455 | } |
---|
2456 | |
---|
2457 | if (retval < 0) |
---|
2458 | { |
---|
2459 | gconf_set_error(err, |
---|
2460 | GCONF_ERROR_LOCK_FAILED, |
---|
2461 | _("Can't write to file `%s': %s"), |
---|
2462 | iorfile, strerror(errno)); |
---|
2463 | close(fd); |
---|
2464 | g_free(iorfile); |
---|
2465 | gconf_lock_destroy(lock); |
---|
2466 | return NULL; |
---|
2467 | } |
---|
2468 | |
---|
2469 | if (close(fd) < 0) |
---|
2470 | { |
---|
2471 | gconf_set_error(err, |
---|
2472 | GCONF_ERROR_LOCK_FAILED, |
---|
2473 | _("Failed to close file `%s': %s"), |
---|
2474 | iorfile, strerror(errno)); |
---|
2475 | g_free(iorfile); |
---|
2476 | gconf_lock_destroy(lock); |
---|
2477 | return NULL; |
---|
2478 | } |
---|
2479 | } |
---|
2480 | } |
---|
2481 | |
---|
2482 | g_free(iorfile); |
---|
2483 | return lock; |
---|
2484 | } |
---|
2485 | |
---|
2486 | gboolean |
---|
2487 | gconf_release_lock(GConfLock* lock, |
---|
2488 | GError** err) |
---|
2489 | { |
---|
2490 | gchar* iorfile; |
---|
2491 | FILE* fp; |
---|
2492 | gchar buf[256] = { '\0' }; |
---|
2493 | gchar* str = NULL; |
---|
2494 | gulong pid; |
---|
2495 | |
---|
2496 | iorfile = g_strconcat(lock->lock_directory, "/ior", NULL); |
---|
2497 | |
---|
2498 | fp = fopen(iorfile, "r"); |
---|
2499 | |
---|
2500 | if (fp == NULL) |
---|
2501 | { |
---|
2502 | gconf_set_error(err, |
---|
2503 | GCONF_ERROR_FAILED, |
---|
2504 | _("Can't open lock file `%s'; assuming it isn't ours: %s"), |
---|
2505 | iorfile, strerror(errno)); |
---|
2506 | g_free(iorfile); |
---|
2507 | return FALSE; |
---|
2508 | } |
---|
2509 | |
---|
2510 | fgets(buf, 255, fp); |
---|
2511 | fclose(fp); |
---|
2512 | |
---|
2513 | /* The lockfile format is <pid>:<ior> for gconfd |
---|
2514 | or <pid>:none for gconftool */ |
---|
2515 | |
---|
2516 | /* get PID to see if it's ours */ |
---|
2517 | pid = strtoul(buf, &str, 10); |
---|
2518 | |
---|
2519 | if (buf == str) |
---|
2520 | { |
---|
2521 | gconf_log(GCL_WARNING, _("Corrupt lock file `%s', removing anyway"), |
---|
2522 | iorfile); |
---|
2523 | |
---|
2524 | } |
---|
2525 | else |
---|
2526 | { |
---|
2527 | if (pid != getpid()) |
---|
2528 | { |
---|
2529 | gconf_set_error(err, |
---|
2530 | GCONF_ERROR_FAILED, |
---|
2531 | _("Didn't create lock file `%s' (creator pid %u, our pid %u; assuming someone took our lock"), |
---|
2532 | iorfile, (guint)pid, (guint)getpid()); |
---|
2533 | g_free(iorfile); |
---|
2534 | return FALSE; |
---|
2535 | } |
---|
2536 | } |
---|
2537 | |
---|
2538 | /* Race condition here, someone could replace the lockfile |
---|
2539 | before we decide whether it's ours; oh well */ |
---|
2540 | unlink(iorfile); |
---|
2541 | |
---|
2542 | g_free(iorfile); |
---|
2543 | |
---|
2544 | if (rmdir(lock->lock_directory) < 0) |
---|
2545 | { |
---|
2546 | gconf_set_error(err, |
---|
2547 | GCONF_ERROR_FAILED, |
---|
2548 | _("Failed to release lock directory `%s': %s"), |
---|
2549 | lock->lock_directory, |
---|
2550 | strerror(errno)); |
---|
2551 | gconf_lock_destroy(lock); |
---|
2552 | return FALSE; |
---|
2553 | } |
---|
2554 | gconf_lock_destroy(lock); |
---|
2555 | return TRUE; |
---|
2556 | } |
---|
2557 | |
---|
2558 | |
---|