diff options
author | Richard Hult <rhult@src.gnome.org> | 2004-04-19 14:42:31 +0000 |
---|---|---|
committer | Richard Hult <rhult@src.gnome.org> | 2004-04-19 14:42:31 +0000 |
commit | 687ae98ebb66a485a8b856769fdd94269d707c08 (patch) | |
tree | e38cc45e326d13bbe7b525a5c905fc408374a290 | |
parent | e78a2665d9ce246aaacd4024bcdc7f370915a4c3 (diff) | |
download | gconf-dbus.tar.gz |
Merge from head.GCONF_DBUS_MERGE_2gconf-dbus
45 files changed, 1985 insertions, 1304 deletions
@@ -1,3 +1,325 @@ +2004-04-19 Mark McLoughlin <mark@skynet.ie> + + Based on a patch from Julio Merino <jmmv@hispabsd.org> + in bug #102825 + + * configure.in: add a --enable-gtk=yes/no/auto (defaults to auto) + +2004-04-19 Mark McLoughlin <mark@skynet.ie> + + Patch Elijah Newren <bugsqueesher@yahoo.com> in bug #138009 + + * examples/basic-gconf-app.c: (config_entry_commit): + return a boolean so we don't crash. + +2004-04-19 Mark McLoughlin <mark@skynet.ie> + + Based on a patch from Ryan Lovett <ryan@ocf.berkeley.edu> + in bug #95198. + + * backends/markup-backend.c: (resolve_address): + backends/xml-backend.c: (resolve_address): check to see + if the dir exists before trying to create it rather than + relying on EEXIST from mkdir. + +2004-04-19 Mark McLoughlin <mark@skynet.ie> + + * backends/dir-utils.[ch], + backends/val-encode.[ch]: remove last remenants + of the BDB backend. + +2004-04-19 Mark McLoughlin <mark@skynet.ie> + + Tracked down by Gustavo Giráldez <gustavo.giraldez@gmx.net> + in bug #139170 + + * gconf/gconfd.c: (logfile_save): don't save default_db explicitly + since its now stored in the same list as the other dbs - but do + make sure that it gets saved as "def" rather than using its full + address list. + +2004-04-16 Colin Walters <walters@redhat.com> + + * gconf/gconf-internals.c (gconf_activate_server): Move temporary + directory creation into daemon code, so that we play better with + SELinux. Patch reviewed by (and several improvements suggested by) + Mark McLoughlin <mark@skynet.ie>. + +2004-04-13 Mark McLoughlin <mark@skynet.ie> + + Fix pointed out by Frédéric L. W. Meunier <1@pervalidus.net>. + + * gconf.m4.in: add quotes around AM_GCONF_SOURCE_2 to + quell autoconf's rudeness. + +2004-04-08 Guntupalli Karunakar <karunakar@freedomink.org> + + * configure.in: Added "gu" (Gujarati) to ALL_LINGUAS. + +2004-04-08 Adam Weinberger <adamw@gnome.org> + + * configure.in: Added en_CA to ALL_LINGUAS. + +2004-04-05 Mark McLoughlin <mark@skynet.ie> + + Revert the --dump behaviour change (not dumping schema defaults) + and add a --ignore-schema-defaults argument which applies to + all arguments which get the value of a key. + + * gconf/gconftool.c: + (main): check that --ignore-schema-defaults is being used with + an option which gets a value. + (list_pairs_in_dir), (dump_entries_in_dir): + respect --ignore-schema-defaults. + (get_maybe_without_default): helper function. + (do_get), (do_get_type), (do_get_list_size), (do_get_list_element): + respect --ignore-schema-defaults. + +2004-04-02 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconftool.c: (set_values), (process_entry): handle + an <entry> with only a <schema_name> correctly. + +2004-04-01 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconftool.c: (dump_entries_in_dir): don't dump + the value if its the schema default. + +2004-04-01 Mark McLoughlin <mark@skynet.ie> + + * gconf/default.path.in: fix the position of the + local-defaults.path include. Bug #137578. + +2004-03-31 Mark McLoughlin <mark@skynet.ie> + + Fix last remaining obvious issue I'm seeing with the previous + patches. gconfd was crashing when removing objects from the + panel. + + * gconf/gconf-database.c: (gconf_database_recursive_unset): + Don't try and propogate a NULL error. + + * gconf/gconf-sources.c: + (gconf_sources_unset_value): create modified_sources when + they it doesn't exist. + (prepend_unset_notify): add a couple of assertions. + (recursive_unset_helper): unset modified_sources between + unsets so that we don't append to the same source list. + +2004-03-30 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-backend.c: (gconf_backend_verify_vtable): + Return TRUE if the vtable is okay. + +2004-03-30 Mark McLoughlin <mark@skynet.ie> + + * doc/gconf/tmpl/gconf-backend.sgml: add some documentation + for set_notify_func(). + +2004-03-30 Mark McLoughlin <mark@skynet.ie> + + * tests/testbackend.c: (foreach_recursive), (sync_and_clear), + (check_unset), (set_value), (get_value): upd. for the fact + we have a copy of the vtale now rather than a pointer to it. + +2004-03-30 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-backend.h: actually add the vtable_size + vtable member. + +2004-03-29 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-database.c: + (safe_g_hash_table_insert): remove - no hash table here. + +2004-03-29 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-engine.h: add gconf_engine_get_for_addresses() + and gconf_engine_get_local_for_addresses(). + + * gconf/gconf.c: + (gconf_engine_connect): implement setting up a database from + an arbitrary stack of sources. + (register_engine): use the concatenation of addresses for the key. + (unregister_engine): free the persistent address and address list on + unregistering. + (lookup_engine): use the concatenation of addresses for the key. + (gconf_engine_get_local_for_addresses): add. + (gconf_engine_get_for_address): update for register_engine change. + (gconf_engine_get_for_addresses): impl support for remote composite dbs. + (update_listener): update for the fact that listeners are now saved using + the persistent name. + + * gconf/GConfX.idl: extend the ConfigServer interface + by adding ConfigServer2 inherting from ConfigServer. + Add ConfigServer2::get_database_for_addresses(). + + * gconf/gconf-backend.c: + (gconf_address_valid), (gconf_get_backend): check the backend + address doesn't contain any special characters. + + * gconf/gconf-database.[ch]: + (source_notify_cb): don't notify unless this change could + actually cause a change for the client. + (gconf_database_notify_listeners): impl. notifying "other" + listeners - clients listening on other stacks which contains + any of the modified sources. + (gconf_database_set), (gconf_database_unset): keep track of + the sources modified by the change and update for the + notify_listeners change. + (gconf_database_recursive_unset): ditto and upd. for the + change in the listeners list returned by + gconf_sources_recursive_unset(). + (gconf_database_get_persistent_name): make the persistent + name a concatenation of the individual addresses instead + of the first address. + + * gconf/gconf-internals.[ch]: + (gconf_address_list_get_persistent_name): impl method similar + to gconf_database_get_persistent_name, except concatenate + the addresses from a GSList. + (gconf_persistent_name_get_address_list): do the reverse. + (gconf_address_list_free): free the list of strings. + + * gconf/gconf-sources.[ch]: + (gconf_sources_new_from_source): allow creating an empty source + list. + (gconf_sources_set_value), + (gconf_sources_unset_value): return the sources modified by + the change. + (prepend_unset_notify), (recursive_unset_helper), + (gconf_sources_recursive_unset): return a list of GConfUnsetNotifys + which contains both the key and the modified source. + (get_address_resource): copy and paste of gconf_address_resource + except it doesn't dup the return value. + (gconf_sources_is_affected): figure out if a change to a particular + key in one source affects the key with a particular stack of sources. + + * gconf/gconfd.[ch]: impl ConfigServer2 inheritance. + (gconfd_get_database): upd for obtain_database change. + (gconfd_get_composite_database): implement. + (init_databases): rename dbs_by_address to dbs_by_addresses. + (set_default_database): register the default db like the others. + (register_database): use the persistent name as the key. + (unregister_database): ditto. + (lookup_database): ditto. + (obtain_database): use a list of addresses, not a single one. + (gconfd_notify_other_listeners): impl notifying listeners + on GConfDatabases other than the one which was changed. + (listener_logentry_restore_and_destroy_foreach): restore by + splitting the address list string. + + * gconf/gconftool.c: (main): enable --config-source without + --direct as it works better now. Also allow --config-source + to be an address list. + +2004-03-29 Mark McLoughlin <mark@skynet.ie> + + * backends/markup-backend.c, + backends/xml-backend.c: initialize the set_notify_func + vtable member. + +2004-03-29 Mark McLoughlin <mark@skynet.ie> + + Re-work the notifications-from-backends patch so that the + backend doesn't have to keep track of a callback per + listener as suggested by Cyrille. + + * gconf/gconf-backend.h: add a set_notify_func() member to + the vtable and remove the callback arg from add_listener(). + + * gconf/gconf-database.c: + (gconf_database_new): set the notification callback here. + (gconf_database_readd_listener): upd. + + * gconf/gconf-sources.[ch]: + (gconf_source_set_notify_func): add. + (gconf_source_add_listener): upd. + (gconf_sources_set_notify_func): add. + (gconf_sources_add_listener): upd. + +2004-03-26 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-database.c: (source_notify_cb): don't leak + the schema name. + + * gconf/gconf-sources.c: + (gconf_sources_add_listener), + (gconf_sources_remove_listener): fix mistake pointed out + by Cyrille. + +2004-03-25 Mark McLoughlin <mark@skynet.ie> + + Allow backends to notify the daemon of changes to entries. + Based on a patch from Cyrille Moureaux <Cyrille.Moureaux@Sun.COM> + in bug #07692. + + * gconf/gconf-backend.h: add add_listener() and + remove_listener() members to the vtable. + + * gconf/gconf-database.c: + (source_notify_cb): re-compute the value and notify + listeners when the backend reports the key has changed. + (gconf_database_readd_listener), + (gconf_database_remove_listener): add/remove backend + listeners. + + * gconf/gconf-sources.[c]: + (gconf_source_add_listener), + (gconf_source_remove_listener), + (gconf_sources_add_listener), + (gconf_sources_remove_listener): impl. the glue. + + * doc/gconf/tmpl/gconf-backend.sgml: update the backend + documentation. + + * backends/markup-backend.c, + backends/xml-backend.c: set the add_listener() and + remove_listener() members to NULL. + +2004-03-24 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-backend.h: add a vtable_size member to + the vtable. + + * gconf/gconf-backend.c: + (gconf_backend_verify_vtable): impl. copying handling + mismatches in vtable sizes and also refuse to use the + backend if any of the functions we require are NULL. + (gconf_get_backend): fixup error handling a bit. + + * gconf/gconf-sources.c: update to take into account + that the we have a copy of the vtable now rather than + just a pointer to it. + + * doc/gconf/tmpl/gconf-backend.sgml: upd. + + * backends/markup-backend.c, + backends/xml-backend.c: add sizeof (GConfBackendVTable) to + the vtable. + +2004-03-24 Mark McLoughlin <mark@skynet.ie> + + * gconf/gconf-database.c: (impl_ConfigDatabase_set): don't + convert the value into a string and then do nothing with it. + +2004-03-30 Mark McLoughlin <mark@skynet.ie> + + * configure.in: bump to 2.7.1. 2.6.x development is on + the gnome-2-6 branch now. + +2004-03-24 Mark McLoughlin <mark@skynet.ie> + + * configure.in: kill the message-of-doom. + +2004-03-22 Guntupalli Karunakar <karunakar@freedomink.org> + + * configure.in: Added "pa" (Punjabi) to ALL_LINGUAS. + +2004-03-22 Mark McLoughlin <mark@skynet.ie> + + * configure.in: post-release bump to 2.6.1. + 2004-03-22 Mark McLoughlin <mark@skynet.ie> * configure.in: Version 2.6.0 diff --git a/backends/dir-utils.c b/backends/dir-utils.c deleted file mode 100644 index db23d192..00000000 --- a/backends/dir-utils.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * GConf BerkeleyDB back-end - * - * Copyright (C) 2000 Sun Microsystems Inc - * Contributed to the GConf project. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#include <errno.h> -#include <dirent.h> - -#include <gconf/gconf-backend.h> -#include <gconf/gconf-internals.h> -#include <gconf/gconf.h> - -/* mode_to_to_mode: copied from xml-dir.c - needs to be a common utility */ -guint -mode_t_to_mode(mode_t orig) -{ - guint mode = 0; - - if (orig & S_IRUSR) - mode |= 0400; - - if (orig & S_IWUSR) - mode |= 0200; - - if (orig & S_IXUSR) - mode |= 0100; - - if (orig & S_IRGRP) - mode |= 0040; - - if (orig & S_IWGRP) - mode |= 0020; - - if (orig & S_IXGRP) - mode |= 0010; - - if (orig & S_IROTH) - mode |= 0004; - - if (orig & S_IWOTH) - mode |= 0002; - - if (orig & S_IXOTH) - mode |= 0001; - - return mode; -} - -static void -free_list_element (gpointer data, gpointer user_data) -{ - g_free (data); -} - -/* g_free()s each element's data, then free's the list */ -void -_gconf_slist_free_all (GSList * list) -{ - if (!list) - return; - g_slist_foreach (list, free_list_element, NULL); - g_slist_free (list); -} - -/* NOTE: body of _gconf_get_root_dir() is taken directly from initial code in - xml-backend.c:resolve_address() */ - -/* parses root directory of a file-based GConf database and checks - * directory existence/writeability/locking - */ -char * -_gconf_get_root_dir (const char *address, guint * pflags, - const gchar * dbtype, GError ** err) -{ - gchar *root_dir; - guint len; - guint dir_mode = 0700; - guint file_mode = 0600; - gint flags = 0; - GConfLock *lock = NULL; - - root_dir = gconf_address_resource (address); - - if (root_dir == NULL) - { - gconf_set_error (err, GCONF_ERROR_BAD_ADDRESS, - _ - ("Couldn't find the %s root directory in the address `%s'"), - dbtype, address); - return NULL; - } - - /* Chop trailing '/' to canonicalize */ - len = strlen (root_dir); - - if (root_dir[len - 1] == '/') - root_dir[len - 1] = '\0'; - - if (mkdir (root_dir, dir_mode) < 0) - { - if (errno != EEXIST) - { - gconf_set_error (err, GCONF_ERROR_FAILED, - _("Could not make directory `%s': %s"), - (gchar *) root_dir, strerror (errno)); - g_free (root_dir); - return NULL; - } - else - { - /* Already exists, base our dir_mode on it */ - struct stat statbuf; - if (stat (root_dir, &statbuf) == 0) - { - dir_mode = mode_t_to_mode (statbuf.st_mode); - /* dir_mode without search bits */ - file_mode = dir_mode & (~0111); - } - } - } - - { - /* See if we're writeable */ - gboolean writeable = FALSE; - int fd; - gchar *testfile; - - testfile = g_strconcat (root_dir, "/.testing.writeability", NULL); - - fd = open (testfile, O_CREAT | O_WRONLY, S_IRWXU); - - if (fd >= 0) - { - writeable = TRUE; - close (fd); - } - - unlink (testfile); - - g_free (testfile); - - if (writeable) - flags |= GCONF_SOURCE_ALL_WRITEABLE; - - /* We only do locking if it's writeable, - which is sort of broken but close enough - */ - if (writeable) - { - gchar *lockdir; - - lockdir = gconf_concat_dir_and_key (root_dir, "%gconf-backend.lock"); - - lock = gconf_get_lock (lockdir, err); - - if (lock != NULL) - gconf_log (GCL_DEBUG, "Acquired %s lock directory `%s'", dbtype, - lockdir); - - g_free (lockdir); - - if (lock == NULL) - { - g_free (root_dir); - return NULL; - } - } - } - - { - /* see if we're readable */ - gboolean readable = FALSE; - DIR *d; - - d = opendir (root_dir); - - if (d != NULL) - { - readable = TRUE; - closedir (d); - } - - if (readable) - flags |= GCONF_SOURCE_ALL_READABLE; - } - - if (!(flags & GCONF_SOURCE_ALL_READABLE) && - !(flags & GCONF_SOURCE_ALL_WRITEABLE)) - { - gconf_set_error (err, GCONF_ERROR_BAD_ADDRESS, - _ - ("Can't read from or write to the %s root directory in the address `%s'"), - dbtype, address); - g_free (root_dir); - return NULL; - } - *pflags = flags; - - return root_dir; -} diff --git a/backends/dir-utils.h b/backends/dir-utils.h deleted file mode 100644 index 67657089..00000000 --- a/backends/dir-utils.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * GConf BerkeleyDB back-end - * - * Copyright (C) 2000 Sun Microsystems Inc - * Contributed to the GConf project. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GCONF_DIR_UTILS_H - -/* g_free()s each element's data, then free's the list */ -extern void _gconf_slist_free_all (GSList * list); - -/* parses root directory of a file-based GConf database and checks - * directory existence/writeability/locking - */ -extern char *_gconf_get_root_dir (const char *address, guint * pflags, - const gchar * dbtype, GError ** err); - -#endif /* GCONF_DIR_UTILS_H */ diff --git a/backends/markup-backend.c b/backends/markup-backend.c index 18e7f702..cc4401d1 100644 --- a/backends/markup-backend.c +++ b/backends/markup-backend.c @@ -132,6 +132,7 @@ static void blow_away_locks (const char *address); static GConfBackendVTable markup_vtable = { + sizeof (GConfBackendVTable), x_shutdown, resolve_address, lock, @@ -150,7 +151,10 @@ static GConfBackendVTable markup_vtable = { sync_all, destroy_source, clear_cache, - blow_away_locks + blow_away_locks, + NULL, /* set_notify_func */ + NULL, /* add_listener */ + NULL /* remove_listener */ }; static void @@ -248,6 +252,7 @@ resolve_address (const char *address, GError **err) { char* root_dir; + struct stat statbuf; MarkupSource* xsource; GConfSource *source; gint flags = 0; @@ -262,27 +267,22 @@ resolve_address (const char *address, if (root_dir == NULL) return NULL; - if (mkdir (root_dir, dir_mode) < 0) + if (stat (root_dir, &statbuf) == 0) { - if (errno != EEXIST) - { - gconf_set_error (err, GCONF_ERROR_FAILED, - _("Could not make directory `%s': %s"), - root_dir, g_strerror (errno)); - g_free (root_dir); - return NULL; - } - else - { - /* Already exists, base our dir_mode on it */ - struct stat statbuf; - if (stat (root_dir, &statbuf) == 0) - { - dir_mode = _gconf_mode_t_to_mode (statbuf.st_mode); - /* dir_mode without search bits */ - file_mode = dir_mode & (~0111); - } - } + /* Already exists, base our dir_mode on it */ + dir_mode = _gconf_mode_t_to_mode (statbuf.st_mode); + + /* dir_mode without search bits */ + file_mode = dir_mode & (~0111); + } + else if (mkdir (root_dir, dir_mode) < 0) + { + /* Error out even on EEXIST - shouldn't happen anyway */ + gconf_set_error (err, GCONF_ERROR_FAILED, + _("Could not make directory `%s': %s"), + root_dir, g_strerror (errno)); + g_free (root_dir); + return NULL; } force_readonly = FALSE; diff --git a/backends/val-encode.c b/backends/val-encode.c deleted file mode 100644 index 8df6fb39..00000000 --- a/backends/val-encode.c +++ /dev/null @@ -1,444 +0,0 @@ -/* - * GConf BerkeleyDB back-end - * - * Copyright (C) 2000 Sun Microsystems Inc Contributed to the GConf project. - * - * This library is free software; you can redistribute it and/or modify it under - * the terms of the GNU Library General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public - * License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <string.h> -#include <stdlib.h> -#include <stdio.h> - -#include <gconf/gconf.h> - -/* required for gconf_value_new_from_string() */ -#include <gconf/gconf-internals.h> - -/* required for _gconf_slist_free_all */ -#include "dir-utils.h" - -/* GConf Value type character identifiers */ -static const char bdb_string = 's'; -static const char bdb_int = 'i'; -static const char bdb_float = 'f'; -static const char bdb_bool = 'b'; -static const char bdb_schema = 'x'; -static const char bdb_list = 'l'; -static const char bdb_pair = 'p'; - -/* Map each character value type id to the corresponding GConfValueType - and vice-versa */ -static struct s_TypeMap -{ - char type; - GConfValueType valuetype; -} -bdb_value_types[] = -{ - { - 's', GCONF_VALUE_STRING} - , - { - 'i', GCONF_VALUE_INT} - , - { - 'f', GCONF_VALUE_FLOAT} - , - { - 'b', GCONF_VALUE_BOOL} - , - { - 'x', GCONF_VALUE_SCHEMA} - , - { - 'l', GCONF_VALUE_LIST} - , - { - 'p', GCONF_VALUE_PAIR} - , - { - '\0', GCONF_VALUE_INVALID} -}; - -/* { Conversion functions using bdb_value_types to map between GConfValueType - * and the corresponding character-based value type identifiers - */ -static GConfValueType -get_value_type (char type) -{ - int i = 0; - - while (bdb_value_types[i].type && (bdb_value_types[i].type != type)) - i++; - return bdb_value_types[i].valuetype; -} - -static char -get_type_for_value_type (GConfValueType valuetype) -{ - int i = 0; - - while (bdb_value_types[i].type - && (bdb_value_types[i].valuetype != valuetype)) - i++; - return bdb_value_types[i].type; -} - -/* } */ - -static char * -append_string (char *buf, const char *string) -{ - if (string) - { - strcpy (buf, string); - return buf + strlen (string) + 1; - } - *buf++ = '\0'; - return buf; -} - -static char tbuf[259]; /* 256 + 3 bytes for "<type>:" and end zero byte */ - -void -_gconf_check_free (char *buf) -{ - if (buf && buf != tbuf) - free (buf); -} - -/* { Functions to size, serialize and de-serialize a GConfValue, which - * is stored in the database as an encoded string. - */ - -/* bdb_size_value returns the encoded size of a value, which is 2 bytes - * for leading type info, plus enough room for the value as a string - * (excluding terminal NULL byte) - */ -static size_t -bdb_size_value (const GConfValue * val) -{ - size_t len = 0; - char *buf = tbuf; - if (!val) - return 3; /* empty values are encoded as a type and a - * null string */ - switch (val->type) - { - case GCONF_VALUE_STRING: - { - char *t = gconf_value_get_string (val) == 0 ? "" : val->d.string_data; - len = strlen (t) + 2; - } - break; - case GCONF_VALUE_INT: - sprintf (buf, "%d", val->d.int_data); - len = strlen (buf) + 2; - break; - case GCONF_VALUE_FLOAT: - sprintf (buf, "%f", (double) gconf_value_get_float (val)); - len = strlen (buf) + 2; - break; - case GCONF_VALUE_BOOL: - len = 3; - break; - case GCONF_VALUE_SCHEMA: - { - GConfSchema *schema = gconf_value_get_schema (val); - len = 3; - if (schema == NULL) - { - return len; - } - if (schema->locale) - len += strlen (schema->locale); /* Schema locale */ - len++; - if (schema->owner) - len += strlen (schema->owner); /* Name of creating application */ - len++; - if (schema->short_desc) - len += strlen (schema->short_desc); /* 40 char or less - * description, no newlines */ - len++; - if (schema->long_desc) - len += strlen (schema->long_desc); /* could be a paragraph or so */ - len++; - len += bdb_size_value (schema->default_value); /* includes type - * information */ - if (!schema->default_value) - { - if (schema->type == GCONF_VALUE_LIST) - len++; /* even an empty list will include the type - * character */ - } - } - break; - case GCONF_VALUE_LIST: - { - GSList *list; - len = 4; - list = gconf_value_get_list (val); - while (list != NULL) - { - len += bdb_size_value ((GConfValue *) list->data) + 1; - list = g_slist_next (list); - } - return len; - } - case GCONF_VALUE_PAIR: - len = 2 + bdb_size_value (gconf_value_get_car (val)) + - bdb_size_value (gconf_value_get_cdr (val)); - case GCONF_VALUE_INVALID: - default: - len = 0; - break; - } - return len; -} - -/* All values are stored in the database as strings; bdb_serialize_value() - * encodes a GConfValue as a string, bdb_restore_value() decodes a - * serialized string back to a value - */ -char * -bdb_serialize_value (const GConfValue * val, size_t * lenp) -{ - char *buf = tbuf; - const char *t; - size_t len = 0; - g_assert (val != 0); - switch (val->type) - { - case GCONF_VALUE_STRING: - t = gconf_value_get_string (val) == 0 ? "" : val->d.string_data; - len = strlen (t) + 3; - if (len > 256) - { - buf = (char *) malloc (len); - } - buf[0] = bdb_string; - buf[1] = ':'; - strcpy (buf + 2, t); - break; - case GCONF_VALUE_INT: - sprintf (buf, "%c:%d", bdb_int, gconf_value_get_int (val)); - len = strlen (buf) + 1; - break; - case GCONF_VALUE_FLOAT: - sprintf (buf, "%c:%f", bdb_float, (double) gconf_value_get_float (val)); - len = strlen (buf) + 1; - break; - case GCONF_VALUE_BOOL: - sprintf (buf, "%c:%d", bdb_bool, gconf_value_get_bool (val) ? 1 : 0); - len = strlen (buf) + 1; - break; - case GCONF_VALUE_SCHEMA: - { - GConfSchema *schema = gconf_value_get_schema (val); - size_t sublen; - char *end; - len = bdb_size_value (val); - buf = (char *) malloc (len); - buf[0] = bdb_schema; - buf[1] = ':'; - if (schema == NULL) - { - buf[2] = '\0'; - return buf; - } - end = &buf[2]; - end = append_string (end, schema->locale); - end = append_string (end, schema->owner); - end = append_string (end, schema->short_desc); - end = append_string (end, schema->long_desc); - if (!schema->default_value) - { - *end++ = get_type_for_value_type (schema->type); - *end++ = ':'; - *end++ = '\0'; - } - else - { - t = bdb_serialize_value (schema->default_value, &sublen); - memcpy (end, t, sublen); - end += sublen; - } - } - break; - case GCONF_VALUE_LIST: - { - GSList *list; - char *end; - size_t sublen; - len = bdb_size_value (val); - buf = (char *) malloc (len); - list = val->d.list_data.list; - buf[0] = bdb_list; - buf[1] = ':'; - buf[2] = get_type_for_value_type (gconf_value_get_list_type (val)); - end = buf + 3; - while (list != NULL) - { - t = bdb_serialize_value ((GConfValue *) list->data, &sublen); - memcpy (end, t, sublen); - end += sublen; - _gconf_check_free (t); - list = g_slist_next (list); - } - *end = '\0'; - } - break; - case GCONF_VALUE_PAIR: - { - size_t sublen; - len = bdb_size_value (val); - buf = (char *) malloc (len); - buf[0] = bdb_pair; - buf[1] = ':'; - len = 2; - t = bdb_serialize_value (gconf_value_get_car (val), &sublen); - if (t) - { - memcpy (buf + len, t, sublen); - len += sublen; - _gconf_check_free (t); - } - else - { - buf[len++] = '\0'; - } - t = bdb_serialize_value (gconf_value_get_cdr (val), &sublen); - if (t) - { - memcpy (buf + len, t, sublen); - len += sublen; - _gconf_check_free (t); - } - else - { - buf[len++] = '\0'; - } - } - break; - case GCONF_VALUE_INVALID: - default: - *lenp = 0; - return NULL; - break; - } - *lenp = len; - return buf; -} - -GConfValue * -bdb_restore_value (const char *srz) -{ - size_t len; - char type; - GError *err; - g_assert (srz != 0); - if ((strlen (srz) < 2) || (srz[1] != ':')) - { - return NULL; - } - type = *srz; - srz += 2; - switch (type) - { - case 's': - return gconf_value_new_from_string (GCONF_VALUE_STRING, srz, &err); - break; - case 'i': - return gconf_value_new_from_string (GCONF_VALUE_INT, srz, &err); - break; - case 'f': - return gconf_value_new_from_string (GCONF_VALUE_FLOAT, srz, &err); - break; - case 'b': - return gconf_value_new_from_string (GCONF_VALUE_BOOL, srz, &err); - break; - case 'x': - { - GConfValue *schema_val = gconf_value_new (GCONF_VALUE_SCHEMA); - GConfValue *val; - GConfSchema *schema = gconf_schema_new (); - len = 4; /* "x:" + (char)type + '\0' */ - if (*srz) - gconf_schema_set_locale (schema, srz); - srz += strlen (srz) + 1; - if (*srz) - gconf_schema_set_owner (schema, srz); - srz += strlen (srz) + 1; - if (*srz) - gconf_schema_set_short_desc (schema, srz); - srz += strlen (srz) + 1; - if (*srz) - gconf_schema_set_long_desc (schema, srz); - srz += strlen (srz) + 1; - val = bdb_restore_value (srz); - gconf_schema_set_type (schema, get_value_type (*srz)); - gconf_schema_set_default_value_nocopy (schema, val); - gconf_value_set_schema (schema_val, schema); - return schema_val; - } - break; - case 'l': - { - GSList *list = NULL; - GConfValue *valuep; - valuep = gconf_value_new (GCONF_VALUE_LIST); - gconf_value_set_list_type (valuep, get_value_type (*srz++)); - while (*srz) - { - list = g_slist_append (list, bdb_restore_value (srz)); - while (*srz) - srz++; - srz++; - } - gconf_value_set_list (valuep, list); - _gconf_slist_free_all (list); - return valuep; - } - break; - case 'p': - { - GConfValue *valuep = NULL; - if (*srz) - { - valuep = gconf_value_new (GCONF_VALUE_PAIR); - gconf_value_set_car (valuep, bdb_restore_value (srz)); - while (*srz) - srz++; - srz++; - if (*srz) - { - gconf_value_set_cdr (valuep, bdb_restore_value (srz)); - } - else - { - gconf_value_free (valuep); - valuep = NULL; - } - } - return valuep; - } - default: - break; - } - return 0; -} - -/* } */ diff --git a/backends/val-encode.h b/backends/val-encode.h deleted file mode 100644 index 7d080a56..00000000 --- a/backends/val-encode.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * GConf BerkeleyDB back-end - * - * Copyright (C) 2000 Sun Microsystems Inc - * Contributed to the GConf project. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef GCONF_VAL_ENCODE_H - -/* Functions to size, serialize and de-serialize a GConfValue, which - * is stored in the database as an encoded string. - */ - -/* All values are stored in the database as strings; bdb_serialize_value() - * encodes a GConfValue as a string, bdb_restore_value() decodes a - * serialized string back to a value - */ -extern char *bdb_serialize_value (const GConfValue * val, size_t * lenp); - -extern GConfValue *bdb_restore_value (const char *srz); - -extern void _gconf_check_free (char *buf); - -#endif /* GCONF_VAL_ENCODE_H */ diff --git a/backends/xml-backend.c b/backends/xml-backend.c index ec209cb0..83adc9e3 100644 --- a/backends/xml-backend.c +++ b/backends/xml-backend.c @@ -209,6 +209,7 @@ static void clear_cache (GConfSource* source); static void blow_away_locks (const char *address); static GConfBackendVTable xml_vtable = { + sizeof (GConfBackendVTable), x_shutdown, resolve_address, lock, @@ -227,7 +228,10 @@ static GConfBackendVTable xml_vtable = { sync_all, destroy_source, clear_cache, - blow_away_locks + blow_away_locks, + NULL, /* set_notify_func */ + NULL, /* add_listener */ + NULL /* remove_listener */ }; static void @@ -309,6 +313,7 @@ get_lock_dir_from_root_dir (const char *root_dir) static GConfSource* resolve_address (const gchar* address, GError** err) { + struct stat statbuf; gchar* root_dir; XMLSource* xsource; GConfSource* source; @@ -324,27 +329,22 @@ resolve_address (const gchar* address, GError** err) if (root_dir == NULL) return NULL; - if (mkdir(root_dir, dir_mode) < 0) + if (stat (root_dir, &statbuf) == 0) { - if (errno != EEXIST) - { - gconf_set_error(err, GCONF_ERROR_FAILED, - _("Could not make directory `%s': %s"), - (gchar*)root_dir, strerror(errno)); - g_free(root_dir); - return NULL; - } - else - { - /* Already exists, base our dir_mode on it */ - struct stat statbuf; - if (stat(root_dir, &statbuf) == 0) - { - dir_mode = _gconf_mode_t_to_mode (statbuf.st_mode); - /* dir_mode without search bits */ - file_mode = dir_mode & (~0111); - } - } + /* Already exists, base our dir_mode on it */ + dir_mode = _gconf_mode_t_to_mode (statbuf.st_mode); + + /* dir_mode without search bits */ + file_mode = dir_mode & (~0111); + } + else if (mkdir (root_dir, dir_mode) < 0) + { + /* Error out even on EEXIST - shouldn't happen anyway */ + gconf_set_error (err, GCONF_ERROR_FAILED, + _("Could not make directory `%s': %s"), + (gchar *)root_dir, g_strerror (errno)); + g_free (root_dir); + return NULL; } force_readonly = FALSE; diff --git a/configure.in b/configure.in index 1c8e3547..eb9828f6 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ AC_INIT(gconf/gconf.h) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(GConf, 2.6.0) +AM_INIT_AUTOMAKE(GConf, 2.7.1) AM_MAINTAINER_MODE @@ -175,10 +175,10 @@ dnl NOTE: We need to use a separate automake conditional for this dnl to make this work with the tarballs. AM_CONDITIONAL(ENABLE_GTK_DOC, test x$enable_gtk_doc = xyes) -AC_ARG_WITH(ipc, [ --with-ipc=[orbit/dbus/both] choose ipc mechanism to use in the daemon, [default=dbus]], with_ipc="$withval", with_ipc=dbus) +AC_ARG_WITH(ipc, [ --with-ipc=[orbit/dbus] Choose ipc mechanism to use in the daemon, [default=dbus]], with_ipc="$withval", with_ipc=dbus) -if test x$with_ipc = xorbit -o x$with_ipc = xboth; then - PKG_CHECK_MODULES(GCONF_ORBIT, ORBit-2.0 >= 2.4.0 linc >= 0.5.0, have_orbit=yes, have_orbit=no) +if test x$with_ipc = xorbit; then + PKG_CHECK_MODULES(GCONF_ORBIT, ORBit-2.0 >= 2.4.0, have_orbit=yes, have_orbit=no) if test x$have_orbit = xno ; then AC_MSG_WARN([ORBit development libraries not found]) have_orbit=no @@ -193,7 +193,7 @@ fi PC_REQUIRES=ORBit-2.0 -if test x$with_ipc = xdbus -o x$with_ipc = xboth; then +if test x$with_ipc = xdbus; then PKG_CHECK_MODULES(GCONF_DBUS, dbus-glib-1 >= 0.20, have_dbus=yes, have_dbus=no) if test x$have_dbus = xyes; then AC_DEFINE(HAVE_DBUS, 1, D-BUS support in the daemon) @@ -222,6 +222,7 @@ AC_SUBST(GCONF_IPC_LIBS) DBUS_SERVICE_DIR=$libdir/dbus-1.0/services AC_SUBST(DBUS_SERVICE_DIR) +AC_ARG_ENABLE(gtk, [ --enable-gtk Enable GTK+ support (for gconf-sanity-check) [default=auto]], enable_gtk="$enableval", enable_gtk=auto) PKGCONFIG_MODULES='gmodule-2.0 >= 2.0.1 gobject-2.0 >= 2.0.1' PKGCONFIG_MODULES_WITH_XML="$PKGCONFIG_MODULES libxml-2.0" @@ -230,9 +231,22 @@ PKGCONFIG_MODULES_WITH_XML_AND_GTK=" $PKGCONFIG_MODULES gtk+-2.0 libxml-2.0" PKG_CHECK_MODULES(DEPENDENT, $PKGCONFIG_MODULES) PKG_CHECK_MODULES(DEPENDENT_WITH_XML, $PKGCONFIG_MODULES_WITH_XML) -PKG_CHECK_MODULES(DEPENDENT_WITH_GTK, $PKGCONFIG_MODULES_WITH_GTK, HAVE_GTK=yes, HAVE_GTK=no) -PKG_CHECK_MODULES(DEPENDENT_WITH_XML_AND_GTK, $PKGCONFIG_MODULES_WITH_XML_AND_GTK, , - DEPENDENT_WITH_XML_AND_GTK_CFLAGS=$DEPENDENT_WITH_XML_CFLAGS DEPENDENT_WITH_XML_AND_GTK_LIBS=$DEPENDENT_WITH_XML_LIBS) + +if test "x$enable_gtk" != "xno"; then + PKG_CHECK_MODULES(DEPENDENT_WITH_GTK, $PKGCONFIG_MODULES_WITH_GTK, HAVE_GTK=yes, HAVE_GTK=no) + PKG_CHECK_MODULES(DEPENDENT_WITH_XML_AND_GTK, $PKGCONFIG_MODULES_WITH_XML_AND_GTK, , + DEPENDENT_WITH_XML_AND_GTK_CFLAGS=$DEPENDENT_WITH_XML_CFLAGS DEPENDENT_WITH_XML_AND_GTK_LIBS=$DEPENDENT_WITH_XML_LIBS) + + if test "x$enable_gtk" = "xyes" && test "x$HAVE_GTK" = "xno"; then + AC_MSG_ERROR([[ +*** Could not find GTK+ 2.0 or greater. +*** Go to http://www.gtk.org/ to get it.]]) + fi +else + HAVE_GTK=no + DEPENDENT_WITH_XML_AND_GTK_CFLAGS=$DEPENDENT_WITH_XML_CFLAGS + DEPENDENT_WITH_XML_AND_GTK_LIBS=$DEPENDENT_WITH_XML_LIBS +fi AM_CONDITIONAL(GTK, test x$HAVE_GTK != xno) @@ -320,8 +334,4 @@ tests/Makefile gconf-2.0.pc ]) -echo " -*** WARNING WARNING WARNING WARNING WARNING -*** This is the unstable branch of gconf -*** The stable branch is version 2.4.x -" + diff --git a/doc/gconf/tmpl/gconf-backend.sgml b/doc/gconf/tmpl/gconf-backend.sgml index b4221da2..0d266678 100644 --- a/doc/gconf/tmpl/gconf-backend.sgml +++ b/doc/gconf/tmpl/gconf-backend.sgml @@ -231,6 +231,7 @@ Should destroy a source obtained with @resolve_address. </tbody></tgroup></informaltable> </para> +@vtable_size: @shutdown: @resolve_address: @lock: @@ -250,6 +251,9 @@ Should destroy a source obtained with @resolve_address. @destroy_source: @clear_cache: @blow_away_locks: +@set_notify_func: +@add_listener: +@remove_listener: <!-- ##### STRUCT GConfBackend ##### --> <para> diff --git a/doc/gconf/tmpl/gconf-engine.sgml b/doc/gconf/tmpl/gconf-engine.sgml index ee1fa636..53f2498b 100644 --- a/doc/gconf/tmpl/gconf-engine.sgml +++ b/doc/gconf/tmpl/gconf-engine.sgml @@ -30,6 +30,15 @@ configuration values. An opaque data type representing one or more configuration sources. </para> +@refcount: +@local_sources: +@address: +@user_data: +@dnotify: +@owner: +@owner_use_count: +@is_default: +@is_local: <!-- ##### FUNCTION gconf_engine_get_default ##### --> <para> diff --git a/doc/gconf/tmpl/gconf-internals.sgml b/doc/gconf/tmpl/gconf-internals.sgml index 9189b2a7..951c5514 100644 --- a/doc/gconf/tmpl/gconf-internals.sgml +++ b/doc/gconf/tmpl/gconf-internals.sgml @@ -332,16 +332,6 @@ This function does not work. Don't use it. @setting: -<!-- ##### FUNCTION gconf_handle_oaf_exception ##### --> -<para> - -</para> - -@ev: -@err: -@Returns: - - <!-- ##### FUNCTION gconf_engine_get_full ##### --> <para> This function is basically for internal use. diff --git a/doc/gconf/tmpl/gconf-sources.sgml b/doc/gconf/tmpl/gconf-sources.sgml index b2de610e..c7008203 100644 --- a/doc/gconf/tmpl/gconf-sources.sgml +++ b/doc/gconf/tmpl/gconf-sources.sgml @@ -109,6 +109,7 @@ gconf-sources @sources: @key: @value: +@modified_sources: @err: @@ -120,6 +121,7 @@ gconf-sources @sources: @key: @locale: +@modified_sources: @err: diff --git a/doc/gconf/tmpl/gconf-unused.sgml b/doc/gconf/tmpl/gconf-unused.sgml index ad639754..cbf1ced7 100644 --- a/doc/gconf/tmpl/gconf-unused.sgml +++ b/doc/gconf/tmpl/gconf-unused.sgml @@ -186,6 +186,15 @@ Returns the ORB GConf is using. @Returns: the ORB GConf is using. +<!-- ##### FUNCTION gconf_handle_oaf_exception ##### --> +<para> + +</para> + +@ev: +@err: +@Returns: + <!-- ##### FUNCTION gconf_init_orb ##### --> <para> Initializes CORBA and a connection to the ORB, sets up authentication, diff --git a/examples/basic-gconf-app.c b/examples/basic-gconf-app.c index d54fda76..6de58e55 100644 --- a/examples/basic-gconf-app.c +++ b/examples/basic-gconf-app.c @@ -341,8 +341,8 @@ create_main_window (GConfClient *client) */ /* Commit changes to the GConf database. */ -static void -config_entry_commit (GtkWidget *entry) +static gboolean +config_entry_commit (GtkWidget *entry, GdkEvent *event, gpointer callback_data) { gchar *text; const gchar *key; @@ -361,6 +361,8 @@ config_entry_commit (GtkWidget *entry) gconf_client_unset (client, key, NULL); g_free (text); + + return FALSE; } /* Create an entry used to edit the given config key */ diff --git a/gconf-2.m4.in b/gconf-2.m4.in index 679506d9..c8281ab9 100644 --- a/gconf-2.m4.in +++ b/gconf-2.m4.in @@ -5,7 +5,7 @@ dnl Defines GCONF_SCHEMA_FILE_DIR which is a filesystem directory where dnl you should install foo.schemas files dnl -AC_DEFUN(AM_GCONF_SOURCE_2, +AC_DEFUN([AM_GCONF_SOURCE_2], [ if test "x$GCONF_SCHEMA_INSTALL_SOURCE" = "x"; then GCONF_SCHEMA_CONFIG_SOURCE=`gconftool-2 --get-default-source` diff --git a/gconf.m4.in b/gconf.m4.in index 679506d9..c8281ab9 100644 --- a/gconf.m4.in +++ b/gconf.m4.in @@ -5,7 +5,7 @@ dnl Defines GCONF_SCHEMA_FILE_DIR which is a filesystem directory where dnl you should install foo.schemas files dnl -AC_DEFUN(AM_GCONF_SOURCE_2, +AC_DEFUN([AM_GCONF_SOURCE_2], [ if test "x$GCONF_SCHEMA_INSTALL_SOURCE" = "x"; then GCONF_SCHEMA_CONFIG_SOURCE=`gconftool-2 --get-default-source` diff --git a/gconf/GConfX.idl b/gconf/GConfX.idl index 7a233551..fa65eb56 100644 --- a/gconf/GConfX.idl +++ b/gconf/GConfX.idl @@ -261,3 +261,8 @@ interface ConfigServer { void shutdown(); }; +interface ConfigServer2 : ConfigServer { + typedef sequence<string> AddressList; + + ConfigDatabase get_database_for_addresses (in AddressList addresses); +}; diff --git a/gconf/default.path.in b/gconf/default.path.in index f726b0e2..57793793 100644 --- a/gconf/default.path.in +++ b/gconf/default.path.in @@ -12,25 +12,21 @@ xml:readonly:@EXPANDED_SYSCONFDIR@/gconf/gconf.xml.mandatory # To read in any mandatory settings that the Sys Admin may have created # prior to a desktop system upgrade. The SysAdmin can stick read-only system # wide sources in this file. - include @EXPANDED_SYSCONFDIR@/gconf/2/local-mandatory.path # Now see where users want us to look - basically the user can stick arbitrary # sources in a ~/.gconf.path file and they're inserted here include "$(HOME)/.gconf.path" +# Give users a default storage location, ~/.gconf +xml:readwrite:$(HOME)/.gconf + # To read in any defaults settings that the Sys Admin may have created # prior to a desktop system upgrade. The SysAdmin can stick default values # system-wide in this file. - include @EXPANDED_SYSCONFDIR@/gconf/2/local-defaults.path -# Give users a default storage location, ~/.gconf - -xml:readwrite:$(HOME)/.gconf - # Finally, look at the systemwide defaults -# (commented out for now) xml:readonly:@EXPANDED_SYSCONFDIR@/gconf/gconf.xml.defaults diff --git a/gconf/gconf-backend.c b/gconf/gconf-backend.c index 3aa55c35..07e63340 100644 --- a/gconf/gconf-backend.c +++ b/gconf/gconf-backend.c @@ -26,6 +26,46 @@ #include <sys/stat.h> #include <unistd.h> + +/* Don't allow special characters in configuration source addresses. + * The important one here is not to allow ';' because we use that + * internally as a list delimiter. See GCONF_DATABASE_LIST_DELIM + */ +static const char invalid_chars[] = " \t\r\n\"$&<>,+=#!()'|{}[]?~`;%\\"; + +static gboolean +gconf_address_valid (const char *address, + char **why_invalid) +{ + const char *s; + + g_return_val_if_fail (address != NULL, FALSE); + + if (why_invalid) + *why_invalid = NULL; + + s = address; + while (*s) + { + const char *inv = invalid_chars; + + while (*inv) + { + if (*inv == *s) + { + if (why_invalid) + *why_invalid = g_strdup_printf(_("`%c' is an invalid character in a configuration storage address"), *s); + return FALSE; + } + ++inv; + } + + ++s; + } + + return TRUE; +} + gchar* gconf_address_backend(const gchar* address) { @@ -178,16 +218,84 @@ gconf_backend_file(const gchar* address) static GHashTable* loaded_backends = NULL; +static gboolean +gconf_backend_verify_vtable (GConfBackendVTable *vtable, + GConfBackendVTable *vtable_copy, + const char *backend_name, + GError **err) +{ + int i; + struct + { + char *name; + gsize offset; + } required_vtable_functions[] = { + { "shutdown", G_STRUCT_OFFSET(GConfBackendVTable, shutdown) }, + { "resolve_address", G_STRUCT_OFFSET(GConfBackendVTable, resolve_address) }, + { "query_value", G_STRUCT_OFFSET(GConfBackendVTable, query_value) }, + { "query_metainfo", G_STRUCT_OFFSET(GConfBackendVTable, query_metainfo) }, + { "set_value", G_STRUCT_OFFSET(GConfBackendVTable, set_value) }, + { "all_entries", G_STRUCT_OFFSET(GConfBackendVTable, all_entries) }, + { "all_subdirs", G_STRUCT_OFFSET(GConfBackendVTable, all_subdirs) }, + { "unset_value", G_STRUCT_OFFSET(GConfBackendVTable, unset_value) }, + { "dir_exists", G_STRUCT_OFFSET(GConfBackendVTable, dir_exists) }, + { "remove_dir", G_STRUCT_OFFSET(GConfBackendVTable, remove_dir) }, + { "set_schema", G_STRUCT_OFFSET(GConfBackendVTable, set_schema) }, + { "sync_all", G_STRUCT_OFFSET(GConfBackendVTable, sync_all) }, + { "destroy_source", G_STRUCT_OFFSET(GConfBackendVTable, destroy_source) }, + { "blow_away_locks", G_STRUCT_OFFSET(GConfBackendVTable, blow_away_locks) } + }; + + if (!vtable) + { + gconf_set_error(err, + GCONF_ERROR_FAILED, _("Backend `%s' failed return a vtable\n"), + backend_name); + return FALSE; + } + + /* Create a copy in case vtable size doesn't match */ + memcpy(vtable_copy, vtable, MIN(vtable->vtable_size, sizeof(GConfBackendVTable))); + + vtable_copy->vtable_size = sizeof(GConfBackendVTable); + + for (i = 0; i < G_N_ELEMENTS(required_vtable_functions); i++) + { + if (G_STRUCT_MEMBER_P(vtable_copy, required_vtable_functions[i].offset) == NULL) + { + gconf_set_error(err, + GCONF_ERROR_FAILED, _("Backend `%s' missing required vtable member `%s'\n"), + backend_name, + required_vtable_functions[i].name); + return FALSE; + } + } + + return TRUE; +} + GConfBackend* gconf_get_backend(const gchar* address, GError** err) { GConfBackend* backend; gchar* name; + gchar* why_invalid; if (loaded_backends == NULL) { loaded_backends = g_hash_table_new(g_str_hash, g_str_equal); } + + why_invalid = NULL; + if (!gconf_address_valid (address, &why_invalid)) + { + g_assert (why_invalid != NULL); + gconf_set_error (err, GCONF_ERROR_BAD_ADDRESS, _("Bad address `%s': %s"), + address, why_invalid); + g_free (why_invalid); + return NULL; + } + name = gconf_address_backend(address); if (name == NULL) @@ -225,10 +333,9 @@ gconf_get_backend(const gchar* address, GError** err) if (module == NULL) { - const gchar* error = g_module_error(); gconf_set_error(err, GCONF_ERROR_FAILED, _("Error opening module `%s': %s\n"), - name, error); + name, g_module_error()); g_free(name); return NULL; } @@ -237,6 +344,10 @@ gconf_get_backend(const gchar* address, GError** err) "gconf_backend_get_vtable", (gpointer*)&get_vtable)) { + gconf_set_error(err, + GCONF_ERROR_FAILED, _("Error initializing module `%s': %s\n"), + name, g_module_error()); + g_module_close(module); g_free(name); return NULL; } @@ -245,7 +356,13 @@ gconf_get_backend(const gchar* address, GError** err) backend->module = module; - backend->vtable = (*get_vtable)(); + if (!gconf_backend_verify_vtable((*get_vtable)(), &backend->vtable, name, err)) + { + g_module_close(module); + g_free(name); + g_free(backend); + return NULL; + } backend->name = name; @@ -287,7 +404,7 @@ gconf_backend_unref(GConfBackend* backend) { GError* error = NULL; - (*backend->vtable->shutdown)(&error); + (*backend->vtable.shutdown)(&error); if (error != NULL) { @@ -319,7 +436,7 @@ gconf_backend_resolve_address (GConfBackend* backend, gchar** iter; GConfSource* retval; - retval = (*backend->vtable->resolve_address)(address, err); + retval = (*backend->vtable.resolve_address)(address, err); if (retval == NULL) return NULL; @@ -362,6 +479,6 @@ gconf_blow_away_locks (const gchar* address) if (backend != NULL) { - (*backend->vtable->blow_away_locks) (address); + (*backend->vtable.blow_away_locks) (address); } } diff --git a/gconf/gconf-backend.h b/gconf/gconf-backend.h index 567b5bbc..a8a3c24f 100644 --- a/gconf/gconf-backend.h +++ b/gconf/gconf-backend.h @@ -33,6 +33,9 @@ typedef struct _GConfBackendVTable GConfBackendVTable; struct _GConfBackendVTable { + /* Set to sizeof (GConfBackendVTable) - used for future proofing */ + gsize vtable_size; + void (* shutdown) (GError** err); GConfSource* (* resolve_address) (const gchar* address, @@ -130,12 +133,23 @@ struct _GConfBackendVTable { /* used by gconf-sanity-check */ void (* blow_away_locks) (const char *address); + + void (* set_notify_func) (GConfSource *source, + GConfSourceNotifyFunc notify_func, + gpointer user_data); + + void (* add_listener) (GConfSource *source, + guint id, + const gchar *namespace_section); + + void (* remove_listener) (GConfSource *source, + guint id); }; struct _GConfBackend { const gchar* name; guint refcount; - GConfBackendVTable* vtable; + GConfBackendVTable vtable; GModule* module; }; @@ -168,6 +182,3 @@ GConfSource* gconf_backend_resolve_address (GConfBackend* backend, void gconf_blow_away_locks (const gchar* address); #endif - - - diff --git a/gconf/gconf-corba-utils.c b/gconf/gconf-corba-utils.c index d87644e7..0738d2e2 100644 --- a/gconf/gconf-corba-utils.c +++ b/gconf/gconf-corba-utils.c @@ -192,7 +192,7 @@ ConfigServer gconf_activate_server (gboolean start_if_not_found, GError **error) { - ConfigServer server; + ConfigServer server = CORBA_OBJECT_NIL; int p[2] = { -1, -1 }; char buf[1]; GError *tmp_err; @@ -200,47 +200,56 @@ gconf_activate_server (gboolean start_if_not_found, char *gconfd_dir; char *lock_dir; GString *failure_log; + struct stat statbuf; CORBA_Environment ev; + gboolean dir_accessible; failure_log = g_string_new (NULL); gconfd_dir = gconf_get_daemon_dir (); - - if (mkdir (gconfd_dir, 0700) < 0 && errno != EEXIST) - gconf_log (GCL_WARNING, _("Failed to create %s: %s"), - gconfd_dir, g_strerror (errno)); - g_free (gconfd_dir); + dir_accessible = stat (gconfd_dir, &statbuf) >= 0; + + if (!dir_accessible && errno != ENOENT) + { + server = CORBA_OBJECT_NIL; + gconf_log (GCL_WARNING, _("Failed to stat %s: %s"), + gconfd_dir, g_strerror (errno)); + } + else if (dir_accessible) + { + g_string_append (failure_log, " 1: "); + lock_dir = gconf_get_lock_dir (); + server = gconf_get_current_lock_holder (lock_dir, failure_log); + g_free (lock_dir); + + /* Confirm server exists */ + CORBA_exception_init (&ev); - g_string_append (failure_log, " 1: "); - lock_dir = gconf_get_lock_dir (); - server = gconf_get_current_lock_holder (lock_dir, failure_log); - g_free (lock_dir); + if (!CORBA_Object_is_nil (server, &ev)) + { + ConfigServer_ping (server, &ev); + + if (ev._major != CORBA_NO_EXCEPTION) + { + server = CORBA_OBJECT_NIL; - /* Confirm server exists */ - CORBA_exception_init (&ev); + g_string_append_printf (failure_log, + _("Server ping error: %s"), + CORBA_exception_id (&ev)); + } + } - if (!CORBA_Object_is_nil (server, &ev)) - { - ConfigServer_ping (server, &ev); - - if (ev._major != CORBA_NO_EXCEPTION) - { - server = CORBA_OBJECT_NIL; + CORBA_exception_free (&ev); - g_string_append_printf (failure_log, - _("Server ping error: %s"), - CORBA_exception_id (&ev)); - } + if (server != CORBA_OBJECT_NIL) + { + g_string_free (failure_log, TRUE); + return server; + } } - - CORBA_exception_free (&ev); - if (server != CORBA_OBJECT_NIL) - { - g_string_free (failure_log, TRUE); - return server; - } + g_free (gconfd_dir); if (start_if_not_found) { diff --git a/gconf/gconf-corba.c b/gconf/gconf-corba.c index 2c318a0d..999ab138 100644 --- a/gconf/gconf-corba.c +++ b/gconf/gconf-corba.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ /* GConf * Copyright (C) 1999, 2000 Red Hat Inc. * @@ -57,11 +58,16 @@ struct _GConfEngine { /* If non-NULL, this is a local engine; local engines don't do notification! */ GConfSources* local_sources; - - /* An address if this is not the default engine; + + /* A list of addresses that make up this db + * if this is not the default engine; * NULL if it's the default */ - gchar *address; + GSList *addresses; + + /* A concatentation of the addresses above. + */ + char *persistent_address; gpointer user_data; GDestroyNotify dnotify; @@ -125,7 +131,7 @@ static ConfigDatabase gconf_engine_get_database (GConfEngine *conf, static void register_engine (GConfEngine *conf); static void unregister_engine (GConfEngine *conf); -static GConfEngine *lookup_engine (const gchar *address); +static GConfEngine *lookup_engine (GSList *addresses); static GConfEngine *lookup_engine_by_database (ConfigDatabase db); @@ -298,9 +304,40 @@ gconf_engine_connect (GConfEngine *conf, return FALSE; /* Error should already be set */ if (conf->is_default) - db = ConfigServer_get_default_database (cs, &ev); + { + db = ConfigServer_get_default_database (cs, &ev); + } + else if (conf->addresses->next == NULL) /* single element list */ + { + db = ConfigServer_get_database (cs, conf->addresses->data, &ev); + } else - db = ConfigServer_get_database (cs, conf->address, &ev); + { + ConfigServer2_AddressList *address_list; + GSList *tmp; + int i; + + address_list = ConfigServer2_AddressList__alloc (); + address_list->_length = address_list->_maximum = g_slist_length (conf->addresses); + address_list->_buffer = ConfigServer2_AddressList_allocbuf (address_list->_length); + address_list->_release = CORBA_TRUE; + + i = 0; + tmp = conf->addresses; + while (tmp != NULL) + { + g_assert (i < address_list->_length); + + address_list->_buffer [i] = CORBA_string_dup (tmp->data); + + tmp = tmp->next; + i++; + } + + db = ConfigServer2_get_database_for_addresses ((ConfigServer2) cs, address_list, &ev); + + CORBA_free (address_list); + } if (gconf_server_broken(&ev)) { @@ -321,7 +358,7 @@ gconf_engine_connect (GConfEngine *conf, if (err) *err = gconf_error_new(GCONF_ERROR_BAD_ADDRESS, _("Server couldn't resolve the address `%s'"), - conf->address ? conf->address : "default"); + conf->persistent_address); return FALSE; } @@ -353,22 +390,30 @@ static GHashTable *engines_by_address = NULL; static void register_engine (GConfEngine *conf) { - g_return_if_fail (conf->address != NULL); + g_return_if_fail (conf->addresses != NULL); + g_assert (conf->persistent_address == NULL); + + conf->persistent_address = + gconf_address_list_get_persistent_name (conf->addresses); + if (engines_by_address == NULL) engines_by_address = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (engines_by_address, conf->address, conf); + g_hash_table_insert (engines_by_address, conf->persistent_address, conf); } static void unregister_engine (GConfEngine *conf) { - g_return_if_fail (conf->address != NULL); g_return_if_fail (engines_by_address != NULL); - - g_hash_table_remove (engines_by_address, conf->address); + g_assert (conf->persistent_address != NULL); + + g_hash_table_remove (engines_by_address, conf->persistent_address); + g_free (conf->persistent_address); + conf->persistent_address = NULL; + if (g_hash_table_size (engines_by_address) == 0) { g_hash_table_destroy (engines_by_address); @@ -378,12 +423,23 @@ unregister_engine (GConfEngine *conf) } static GConfEngine * -lookup_engine (const gchar *address) +lookup_engine (GSList *addresses) { - if (engines_by_address) - return g_hash_table_lookup (engines_by_address, address); - else - return NULL; + if (engines_by_address != NULL) + { + GConfEngine *retval; + char *key; + + key = gconf_address_list_get_persistent_name (addresses); + + retval = g_hash_table_lookup (engines_by_address, key); + + g_free (key); + + return retval; + } + + return NULL; } @@ -415,6 +471,24 @@ gconf_engine_get_local (const gchar* address, return conf; } +GConfEngine * +gconf_engine_get_local_for_addresses (GSList *addresses, + GError **err) +{ + GConfEngine *conf; + + g_return_val_if_fail (addresses != NULL, NULL); + g_return_val_if_fail (err == NULL || *err == NULL, NULL); + + conf = gconf_engine_blank (FALSE); + + conf->local_sources = gconf_sources_new_from_addresses (addresses, err); + + g_assert (gconf_engine_is_local (conf)); + + return conf; +} + GConfEngine* gconf_engine_get_default (void) { @@ -444,19 +518,65 @@ gconf_engine_get_default (void) } GConfEngine* -gconf_engine_get_for_address (const gchar* address, GError** err) +gconf_engine_get_for_address (const gchar *address, + GError **err) +{ + GConfEngine *conf; + GSList *addresses; + + addresses = g_slist_append (NULL, g_strdup (address)); + + conf = lookup_engine (addresses); + + if (conf == NULL) + { + conf = gconf_engine_blank (TRUE); + + conf->is_default = FALSE; + conf->addresses = addresses; + + if (!gconf_engine_connect (conf, TRUE, err)) + { + gconf_engine_unref (conf); + return NULL; + } + + register_engine (conf); + } + else + { + g_free (addresses->data); + g_slist_free (addresses); + conf->refcount += 1; + } + + return conf; +} + +GConfEngine* +gconf_engine_get_for_addresses (GSList *addresses, GError** err) { GConfEngine* conf; - conf = lookup_engine (address); + conf = lookup_engine (addresses); if (conf == NULL) { - conf = gconf_engine_blank(TRUE); + GSList *tmp; + + conf = gconf_engine_blank (TRUE); conf->is_default = FALSE; - conf->address = g_strdup (address); + conf->addresses = NULL; + tmp = addresses; + while (tmp != NULL) + { + conf->addresses = g_slist_append (conf->addresses, + g_strdup (tmp->data)); + tmp = tmp->next; + } + if (!gconf_engine_connect (conf, TRUE, err)) { gconf_engine_unref (conf); @@ -546,11 +666,17 @@ gconf_engine_unref(GConfEngine* conf) (* conf->dnotify) (conf->user_data); } - /* do this after removing the notifications, - to avoid funky race conditions */ - if (conf->address) - unregister_engine (conf); - + if (conf->addresses) + { + gconf_address_list_free (conf->addresses); + conf->addresses = NULL; + } + + if (conf->persistent_address) + { + unregister_engine (conf); + } + /* Release the ConfigDatabase */ gconf_engine_detach (conf); @@ -1096,7 +1222,7 @@ gconf_engine_set (GConfEngine* conf, const gchar* key, { GError* error = NULL; - gconf_sources_set_value(conf->local_sources, key, value, &error); + gconf_sources_set_value(conf->local_sources, key, value, NULL, &error); if (error != NULL) { @@ -1174,7 +1300,7 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err) { GError* error = NULL; - gconf_sources_unset_value(conf->local_sources, key, NULL, &error); + gconf_sources_unset_value(conf->local_sources, key, NULL, NULL, &error); if (error != NULL) { @@ -2279,7 +2405,15 @@ update_listener (PortableServer_Servant _servant, if (strcmp (address, "def") == 0) conf = default_engine; else - conf = lookup_engine (address); + { + GSList *addresses; + + addresses = gconf_persistent_name_get_address_list (address); + + conf = lookup_engine (addresses); + + gconf_address_list_free (addresses); + } if (conf) gconf_engine_set_database (conf, diff --git a/gconf/gconf-database-corba.c b/gconf/gconf-database-corba.c index 4d969eb8..0426f906 100644 --- a/gconf/gconf-database-corba.c +++ b/gconf/gconf-database-corba.c @@ -211,7 +211,6 @@ impl_ConfigDatabase_set(PortableServer_Servant servant, CORBA_Environment * ev) { GConfDatabase *db = DB_FROM_SERVANT (servant); - gchar* str; GConfValue* val; GError* error = NULL; @@ -232,15 +231,16 @@ impl_ConfigDatabase_set(PortableServer_Servant servant, return; } - str = gconf_value_to_string(val); - #if 0 - /* reduce traffice to the logfile */ - gconf_log(GCL_DEBUG, "Received request to set key `%s' to `%s'", key, str); -#endif - - g_free(str); + { + gchar* str = gconf_value_to_string(val); + /* reduce traffice to the logfile */ + gconf_log(GCL_DEBUG, "Received request to set key `%s' to `%s'", key, str); + + g_free(str); + } +#endif gconf_database_set(db, key, val, &error); @@ -880,6 +880,8 @@ gconf_database_corba_readd_listener (GConfDatabase *db, cnxn = gconf_listeners_add (db->listeners, where, l, (GFreeFunc)listener_destroy); + gconf_sources_add_listener (db->sources, cnxn, where); + if (l->parent.name == NULL) l->parent.name = g_strdup_printf ("%u", cnxn); @@ -962,6 +964,8 @@ gconf_database_corba_remove_listener (GConfDatabase *db, err->message); g_error_free (err); } + + gconf_sources_remove_listener (db->sources, cnxn); /* calls destroy notify */ gconf_listeners_remove (db->listeners, cnxn); @@ -1019,10 +1023,12 @@ notify_listeners_cb(GConfListeners* listeners, void gconf_database_corba_notify_listeners (GConfDatabase *db, + GConfSources *modified_sources, const gchar *key, const GConfValue *value, gboolean is_default, - gboolean is_writable) + gboolean is_writable, + gboolean notify_others) { ListenerNotifyClosure closure; GSList* tmp; @@ -1053,6 +1059,16 @@ gconf_database_corba_notify_listeners (GConfDatabase *db, tmp = g_slist_next(tmp); } + if (notify_others) + { + g_return_if_fail (modified_sources != NULL); + + gconfd_notify_other_listeners (db, modified_sources, key); + + g_list_free (modified_sources->sources); + g_free (modified_sources); + } + CORBA_free (closure.value); } diff --git a/gconf/gconf-database-corba.h b/gconf/gconf-database-corba.h index 48cf964b..a96a2b38 100644 --- a/gconf/gconf-database-corba.h +++ b/gconf/gconf-database-corba.h @@ -45,11 +45,12 @@ CORBA_unsigned_long gconf_database_corba_readd_listener (GConfDatabase * const gchar *where); void gconf_database_corba_notify_listeners (GConfDatabase *db, + GConfSources *modified_sources, const gchar *key, const GConfValue *value, gboolean is_default, - gboolean is_writable); - + gboolean is_writable, + gboolean notify_others); #endif diff --git a/gconf/gconf-database-dbus.c b/gconf/gconf-database-dbus.c index 0821c9e1..2285b9f4 100644 --- a/gconf/gconf-database-dbus.c +++ b/gconf/gconf-database-dbus.c @@ -35,8 +35,7 @@ struct _GConfDatabaseDBus { GConfDatabase *db; DBusConnection *conn; - char *address; - char *object_path; + char *object_path; /* Information about clients that want notification. */ GHashTable *notifications; @@ -120,15 +119,15 @@ database_unregistered_func (DBusConnection *connection, GConfDatabaseDBus *db) } static DBusHandlerResult -database_message_func (DBusConnection *connection, - DBusMessage *message, +database_message_func (DBusConnection *connection, + DBusMessage *message, GConfDatabaseDBus *db) { if (gconfd_dbus_check_in_shutdown (connection, message)) { return DBUS_HANDLER_RESULT_HANDLED; } - + if (dbus_message_is_method_call (message, GCONF_DBUS_DATABASE_INTERFACE, GCONF_DBUS_DATABASE_LOOKUP)) { @@ -177,16 +176,18 @@ database_message_func (DBusConnection *connection, else if (dbus_message_is_method_call (message, GCONF_DBUS_DATABASE_INTERFACE, GCONF_DBUS_DATABASE_ADD_NOTIFY)) { - database_handle_add_notify (connection, message, db); + database_handle_add_notify (connection, message, db); } else if (dbus_message_is_method_call (message, GCONF_DBUS_DATABASE_INTERFACE, GCONF_DBUS_DATABASE_REMOVE_NOTIFY)) { - database_handle_remove_notify (connection, message, db); - } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + database_handle_remove_notify (connection, message, db); } - + else + { + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + return DBUS_HANDLER_RESULT_HANDLED; } @@ -247,8 +248,8 @@ database_handle_service_deleted (DBusConnection *connection, } static void -database_handle_lookup (DBusConnection *conn, - DBusMessage *message, +database_handle_lookup (DBusConnection *conn, + DBusMessage *message, GConfDatabaseDBus *db) { GConfValue *value; @@ -256,8 +257,8 @@ database_handle_lookup (DBusConnection *conn, gchar *key; gchar *locale; GConfLocaleList *locales; - gboolean use_schema_default; - GError *gerror = NULL; + gboolean use_schema_default; + GError *gerror = NULL; if (!gconfd_dbus_get_message_args (conn, message, DBUS_TYPE_STRING, &key, @@ -265,7 +266,7 @@ database_handle_lookup (DBusConnection *conn, DBUS_TYPE_BOOLEAN, &use_schema_default, 0)) return; - + locales = gconfd_locale_cache_lookup (locale); dbus_free (locale); @@ -276,29 +277,33 @@ database_handle_lookup (DBusConnection *conn, dbus_free (key); if (gconfd_dbus_set_exception (conn, message, &gerror)) - return; + goto fail; reply = dbus_message_new_method_return (message); gconf_dbus_message_append_gconf_value (reply, value); dbus_connection_send (conn, reply, NULL); dbus_message_unref (reply); + + fail: + if (value) + gconf_value_free (value); } static void -database_handle_lookup_ext (DBusConnection *conn, - DBusMessage *message, +database_handle_lookup_ext (DBusConnection *conn, + DBusMessage *message, GConfDatabaseDBus *db) { GConfValue *value; - gchar *schema_name; - gboolean value_is_default; - gboolean value_is_writable; + gchar *schema_name; + gboolean value_is_default; + gboolean value_is_writable; DBusMessage *reply; gchar *key; gchar *locale; GConfLocaleList *locales; - gboolean use_schema_default; - GError *gerror = NULL; + gboolean use_schema_default; + GError *gerror = NULL; if (!gconfd_dbus_get_message_args (conn, message, DBUS_TYPE_STRING, &key, @@ -306,7 +311,7 @@ database_handle_lookup_ext (DBusConnection *conn, DBUS_TYPE_BOOLEAN, &use_schema_default, 0)) return; - + locales = gconfd_locale_cache_lookup (locale); dbus_free (locale); @@ -316,7 +321,7 @@ database_handle_lookup_ext (DBusConnection *conn, &value_is_writable, &gerror); if (gconfd_dbus_set_exception (conn, message, &gerror)) - return; + goto fail; reply = dbus_message_new_method_return (message); gconf_dbus_message_append_entry (reply, @@ -325,18 +330,22 @@ database_handle_lookup_ext (DBusConnection *conn, value_is_default, value_is_writable, schema_name); - - dbus_free (key); - gconf_value_free (value); - g_free (schema_name); - + dbus_connection_send (conn, reply, NULL); dbus_message_unref (reply); + + fail: + dbus_free (key); + + if (value) + gconf_value_free (value); + + g_free (schema_name); } static void -database_handle_set (DBusConnection *conn, - DBusMessage *message, +database_handle_set (DBusConnection *conn, + DBusMessage *message, GConfDatabaseDBus *db) { gchar *key; @@ -364,8 +373,8 @@ database_handle_set (DBusConnection *conn, } static void -database_handle_unset (DBusConnection *conn, - DBusMessage *message, +database_handle_unset (DBusConnection *conn, + DBusMessage *message, GConfDatabaseDBus *db) { gchar *key; @@ -379,6 +388,12 @@ database_handle_unset (DBusConnection *conn, 0)) return; + if (locale[0] == '\0') + { + dbus_free (locale); + locale = NULL; + } + gconf_database_unset (db->db, key, locale, &gerror); dbus_free (key); dbus_free (locale); @@ -408,7 +423,13 @@ database_handle_recursive_unset (DBusConnection *conn, DBUS_TYPE_UINT32, &unset_flags, 0)) return; - + + if (locale[0] == '\0') + { + dbus_free (locale); + locale = NULL; + } + gconf_database_recursive_unset (db->db, key, locale, unset_flags, &gerror); dbus_free (key); dbus_free (locale); @@ -683,8 +704,9 @@ ensure_initialized (void) } GConfDatabaseDBus * -gconf_database_dbus_get (DBusConnection *conn, const gchar *address, - GError **gerror) +gconf_database_dbus_get (DBusConnection *conn, + GSList *addresses, + GError **gerror) { GConfDatabaseDBus *dbus_db = NULL; GConfDatabase *db; @@ -692,18 +714,23 @@ gconf_database_dbus_get (DBusConnection *conn, const gchar *address, ensure_initialized (); - db = gconfd_lookup_database (address); + db = gconfd_lookup_database (addresses); if (!db) { - db = gconfd_obtain_database (address, gerror); + db = gconfd_obtain_database (addresses, gerror); if (!db) { - gconf_log (GCL_WARNING, _("Database not found: %s"), address); + char *name; + + name = gconf_address_list_get_persistent_name (addresses); + gconf_log (GCL_WARNING, _("Database not found: %s"), name); + g_free (name); + return NULL; } } - if (!address) + if (!addresses) dbus_db = default_db; else dbus_db = g_hash_table_lookup (databases, &db); @@ -715,14 +742,12 @@ gconf_database_dbus_get (DBusConnection *conn, const gchar *address, dbus_db->db = db; dbus_db->conn = conn; - if (!address) + if (!addresses) { - dbus_db->address = NULL; default_db = dbus_db; } else { - dbus_db->address = g_strdup (address); g_hash_table_insert (databases, &db, dbus_db); } @@ -775,16 +800,19 @@ gconf_database_dbus_get_path (GConfDatabaseDBus *db) void gconf_database_dbus_notify_listeners (GConfDatabase *db, + GConfSources *modified_sources, const gchar *key, const GConfValue *value, gboolean is_default, - gboolean is_writable) + gboolean is_writable, + gboolean notify_others) { GConfDatabaseDBus *dbus_db = NULL; char *dir, *sep; GList *l; NotificationData *notification; DBusMessage *message; + gboolean last; if (db == default_db->db) dbus_db = default_db; @@ -800,11 +828,14 @@ gconf_database_dbus_notify_listeners (GConfDatabase *db, * remove the leaf, lookup again, remove the leaf, and so on until a match is * found. Notify the clients (identified by their base service) that * correspond to the found namespace. - */ + */ + last = FALSE; while (1) { notification = g_hash_table_lookup (dbus_db->notifications, dir); + g_print ("try '%s', %p\n", dir, notification); + if (notification) { for (l = notification->clients; l; l = l->next) @@ -832,13 +863,31 @@ gconf_database_dbus_notify_listeners (GConfDatabase *db, dbus_message_unref (message); } } + + if (last) + break; sep = strrchr (dir, '/'); + + /* Special case to catch notifications on the root. */ if (sep == dir) - break; - - *sep = '\0'; + { + last = TRUE; + sep[1] = '\0'; + } + else + *sep = '\0'; } g_free (dir); + + if (notify_others) + { + g_return_if_fail (modified_sources != NULL); + + gconfd_notify_other_listeners (db, modified_sources, key); + + g_list_free (modified_sources->sources); + g_free (modified_sources); + } } diff --git a/gconf/gconf-database-dbus.h b/gconf/gconf-database-dbus.h index 46c2b9c9..042db43d 100644 --- a/gconf/gconf-database-dbus.h +++ b/gconf/gconf-database-dbus.h @@ -25,16 +25,17 @@ typedef struct _GConfDatabaseDBus GConfDatabaseDBus; -GConfDatabaseDBus * gconf_database_dbus_get (DBusConnection *conn, - const gchar *address, - GError **error); -void gconf_database_dbus_unregister_all (void); -const gchar * gconf_database_dbus_get_path (GConfDatabaseDBus *db); +GConfDatabaseDBus *gconf_database_dbus_get (DBusConnection *conn, + GSList *addresses, + GError **error); +void gconf_database_dbus_unregister_all (void); +const gchar * gconf_database_dbus_get_path (GConfDatabaseDBus *db); +void gconf_database_dbus_notify_listeners (GConfDatabase *db, + GConfSources *modified_sources, + const gchar *key, + const GConfValue *value, + gboolean is_default, + gboolean is_writable, + gboolean notify_others); - -void gconf_database_dbus_notify_listeners (GConfDatabase *db, - const gchar *key, - const GConfValue *value, - gboolean is_default, - gboolean is_writable); #endif diff --git a/gconf/gconf-database.c b/gconf/gconf-database.c index e890f546..701a6ea3 100644 --- a/gconf/gconf-database.c +++ b/gconf/gconf-database.c @@ -32,34 +32,17 @@ #endif #ifdef HAVE_DBUS #include "gconfd-dbus.h" -#endif -/* This makes hash table safer when debugging */ -#ifndef GCONF_ENABLE_DEBUG -#define safe_g_hash_table_insert g_hash_table_insert -#else -static void -safe_g_hash_table_insert(GHashTable* ht, gpointer key, gpointer value) -{ - gpointer oldkey = NULL, oldval = NULL; - - if (g_hash_table_lookup_extended(ht, key, &oldkey, &oldval)) - { - gconf_log(GCL_WARNING, "Hash key `%s' is already in the table!", - (gchar*) key); - return; - } - else - { - g_hash_table_insert(ht, key, value); - } -} +#include "gconf-database-dbus.h" #endif /* * Forward decls */ -static void gconf_database_really_sync(GConfDatabase* db); +static void gconf_database_really_sync (GConfDatabase* db); +static void source_notify_cb (GConfSource *source, + const gchar *location, + GConfDatabase *db); GConfDatabase* gconf_database_new (GConfSources *sources) @@ -72,6 +55,10 @@ gconf_database_new (GConfSources *sources) db->sources = sources; + gconf_sources_set_notify_func (db->sources, + (GConfSourceNotifyFunc) source_notify_cb, + db); + db->last_access = time(NULL); db->sync_idle = 0; @@ -118,6 +105,8 @@ gconf_database_free (GConfDatabase *db) gconf_listeners_free(db->listeners); gconf_sources_free(db->sources); + + /* FIXME: might need to null out things here. */ } g_free (db->persistent_name); @@ -212,6 +201,67 @@ gconf_database_schedule_sync(GConfDatabase* db) } } +static void +source_notify_cb (GConfSource *source, + const gchar *location, + GConfDatabase *db) +{ + g_return_if_fail (source != NULL); + g_return_if_fail (location != NULL); + g_return_if_fail (db != NULL); + + if (gconf_sources_is_affected (db->sources, source, location)) + { + GConfValue *value; + GError *error; + gboolean is_default; + gboolean is_writable; + + error = NULL; + is_default = is_writable = FALSE; + + value = gconf_database_query_value (db, + location, + NULL, + TRUE, + NULL, + &is_default, + &is_writable, + &error); + if (error != NULL) + { + gconf_log (GCL_WARNING, + _("Error obtaining new value for `%s' after change notification from backend `%s': %s"), + location, + source->address, + error->message); + g_error_free (error); + return; + } + +#ifdef HAVE_ORBIT + gconf_database_corba_notify_listeners (db, + NULL, + location, + value, + is_default, + is_writable, + FALSE); +#endif +#ifdef HAVE_DBUS + gconf_database_dbus_notify_listeners (db, + NULL, + location, + value, + is_default, + is_writable, + FALSE); +#endif + + gconf_value_free (value); + } +} + GConfValue* gconf_database_query_value (GConfDatabase *db, const gchar *key, @@ -269,6 +319,7 @@ gconf_database_set (GConfDatabase *db, GError **err) { GError *error = NULL; + GConfSources *modified_sources; g_assert(db->listeners != NULL); g_return_if_fail(err == NULL || *err == NULL); @@ -280,10 +331,12 @@ gconf_database_set (GConfDatabase *db, gconf_log(GCL_DEBUG, "Received request to set key `%s'", key); #endif - gconf_sources_set_value(db->sources, key, value, &error); + gconf_sources_set_value(db->sources, key, value, &modified_sources, &error); if (error) - { + { + g_assert (modified_sources == NULL); + gconf_log(GCL_ERR, _("Error setting value for `%s': %s"), key, error->message); @@ -295,27 +348,27 @@ gconf_database_set (GConfDatabase *db, { gconf_database_schedule_sync(db); + /* Can't possibly be the default, since we just set it, + * and must be writable since setting it succeeded. + */ #ifdef HAVE_ORBIT - gconf_database_corba_notify_listeners(db, key, value, - /* Can't possibly be the default, - since we just set it, - and must be writable since - setting it succeeded. - */ - FALSE, - TRUE); + gconf_database_corba_notify_listeners (db, + modified_sources, + key, + value, + FALSE, + TRUE, + TRUE); #endif #ifdef HAVE_DBUS - gconf_database_dbus_notify_listeners(db, key, value, - /* Can't possibly be the default, - since we just set it, - and must be writable since - setting it succeeded. - */ + gconf_database_dbus_notify_listeners (db, + modified_sources, + key, + value, FALSE, + TRUE, TRUE); #endif - } } @@ -326,7 +379,8 @@ gconf_database_unset (GConfDatabase *db, GError **err) { GError* error = NULL; - + GConfSources *modified_sources = NULL; + g_return_if_fail(err == NULL || *err == NULL); g_assert(db->listeners != NULL); @@ -335,10 +389,12 @@ gconf_database_unset (GConfDatabase *db, gconf_log(GCL_DEBUG, "Received request to unset key `%s'", key); - gconf_sources_unset_value(db->sources, key, locale, &error); + gconf_sources_unset_value(db->sources, key, locale, &modified_sources, &error); if (error != NULL) { + g_assert (modified_sources == NULL); + gconf_log(GCL_ERR, _("Error unsetting `%s': %s"), key, error->message); @@ -375,10 +431,22 @@ gconf_database_unset (GConfDatabase *db, gconf_database_schedule_sync(db); #ifdef HAVE_ORBIT - gconf_database_corba_notify_listeners(db, key, def_value, TRUE, is_writable); + gconf_database_corba_notify_listeners(db, + modified_sources, + key, + def_value, + TRUE, + is_writable, + TRUE); #endif #ifdef HAVE_DBUS - gconf_database_dbus_notify_listeners(db, key, def_value, TRUE, is_writable); + gconf_database_dbus_notify_listeners(db, + modified_sources, + key, + def_value, + TRUE, + is_writable, + TRUE); #endif if (def_value != NULL) @@ -415,6 +483,8 @@ gconf_database_recursive_unset (GConfDatabase *db, */ if (error != NULL) { + g_assert (notifies == NULL); + gconf_log (GCL_ERR, _("Error unsetting \"%s\": %s"), key, error->message); @@ -433,22 +503,21 @@ gconf_database_recursive_unset (GConfDatabase *db, const gchar* locale_list[] = { NULL, NULL }; gboolean is_writable = TRUE; gboolean is_default = TRUE; - char *notify_key = tmp->data; - + GConfUnsetNotify *notify = tmp->data; + locale_list[0] = locale; new_value = gconf_database_query_value (db, - notify_key, + notify->key, locale_list, TRUE, NULL, &is_default, &is_writable, &error); - if (error) { gconf_log (GCL_ERR, _("Error getting new value for \"%s\": %s"), - notify_key, error->message); + notify->key, error->message); g_propagate_error (err, error); error = NULL; } @@ -456,17 +525,28 @@ gconf_database_recursive_unset (GConfDatabase *db, gconf_database_schedule_sync (db); #ifdef HAVE_ORBIT - gconf_database_corba_notify_listeners (db, notify_key, new_value, - is_default, is_writable); + gconf_database_corba_notify_listeners (db, + notify->modified_sources, + notify->key, + new_value, + is_default, + is_writable, + TRUE); #endif #ifdef HAVE_DBUS - gconf_database_dbus_notify_listeners (db, notify_key, new_value, - is_default, is_writable); + gconf_database_dbus_notify_listeners (db, + notify->modified_sources, + notify->key, + new_value, + is_default, + is_writable, + TRUE); #endif if (new_value) gconf_value_free (new_value); - g_free (notify_key); + g_free (notify->key); + g_free (notify); tmp = tmp->next; } @@ -646,22 +726,46 @@ gconf_database_clear_cache (GConfDatabase *db, gconf_sources_clear_cache(db->sources); } -const gchar* +const gchar * gconf_database_get_persistent_name (GConfDatabase *db) { - if (db->persistent_name == NULL) + GList *tmp; + GString *str = NULL; + + if (db->persistent_name != NULL) + return db->persistent_name; + + if (db->sources == NULL || db->sources->sources == NULL) { - if (db->sources->sources) - db->persistent_name = - g_strdup (((GConfSource*)db->sources->sources->data)->address); + return db->persistent_name; + } + + tmp = db->sources->sources; + while (tmp != NULL) + { + GConfSource *source = tmp->data; + + if (str == NULL) + { + str = g_string_new (source->address); + } else - db->persistent_name = g_strdup ("empty"); + { + g_string_append_c (str, GCONF_DATABASE_LIST_DELIM); + g_string_append (str, source->address); + } + + tmp = tmp->next; } - return db->persistent_name; + g_assert (str != NULL); + + db->persistent_name = str->str; + g_string_free (str, FALSE); + + return db->persistent_name; } - /* * Locale hash */ diff --git a/gconf/gconf-dbus-utils.c b/gconf/gconf-dbus-utils.c index f6881a27..054f3a77 100644 --- a/gconf/gconf-dbus-utils.c +++ b/gconf/gconf-dbus-utils.c @@ -362,7 +362,7 @@ gconf_dbus_message_iter_append_gconf_value (DBusMessageIter *iter, { int *array; - array = g_new (dbus_int32_t, len); + array = g_new (dbus_int32_t, len + 1); i = 0; while (list) @@ -383,7 +383,7 @@ gconf_dbus_message_iter_append_gconf_value (DBusMessageIter *iter, { double *array; - array = g_new (double, len); + array = g_new (double, len + 1); i = 0; while (list) @@ -404,7 +404,7 @@ gconf_dbus_message_iter_append_gconf_value (DBusMessageIter *iter, { unsigned char *array; - array = g_new (unsigned char, len); + array = g_new (unsigned char, len + 1); i = 0; while (list) diff --git a/gconf/gconf-dbus-utils.h b/gconf/gconf-dbus-utils.h index e0df9742..3554a33b 100644 --- a/gconf/gconf-dbus-utils.h +++ b/gconf/gconf-dbus-utils.h @@ -25,86 +25,69 @@ #include <gconf/gconf.h> #include <gconf/gconf-value.h> -#define GCONF_DBUS_SERVICE "org.gnome.GConf" +#define GCONF_DBUS_SERVICE "org.gnome.GConf" -#define GCONF_DBUS_SERVER_INTERFACE "org.gnome.GConf.Server" -#define GCONF_DBUS_DATABASE_INTERFACE "org.gnome.GConf.Database" +#define GCONF_DBUS_SERVER_INTERFACE "org.gnome.GConf.Server" +#define GCONF_DBUS_DATABASE_INTERFACE "org.gnome.GConf.Database" -#define GCONF_DBUS_SERVER_OBJECT "/org/gnome/GConf/Server" +#define GCONF_DBUS_SERVER_OBJECT "/org/gnome/GConf/Server" -#define GCONF_DBUS_SERVER_GET_DEFAULT_DB "GetDefaultDatabase" -#define GCONF_DBUS_SERVER_GET_DB "GetDatabase" -#define GCONF_DBUS_SERVER_SHUTDOWN "Shutdown" +#define GCONF_DBUS_SERVER_GET_DEFAULT_DB "GetDefaultDatabase" +#define GCONF_DBUS_SERVER_GET_DB "GetDatabase" +#define GCONF_DBUS_SERVER_SHUTDOWN "Shutdown" -#define GCONF_DBUS_DATABASE_LOOKUP "Lookup" +#define GCONF_DBUS_DATABASE_LOOKUP "Lookup" #define GCONF_DBUS_DATABASE_LOOKUP_EXTENDED "LookupExtended" -#define GCONF_DBUS_DATABASE_SET "Set" -#define GCONF_DBUS_DATABASE_UNSET "UnSet" +#define GCONF_DBUS_DATABASE_SET "Set" +#define GCONF_DBUS_DATABASE_UNSET "Unset" #define GCONF_DBUS_DATABASE_RECURSIVE_UNSET "RecursiveUnset" -#define GCONF_DBUS_DATABASE_DIR_EXISTS "DirExists" +#define GCONF_DBUS_DATABASE_DIR_EXISTS "DirExists" #define GCONF_DBUS_DATABASE_GET_ALL_ENTRIES "AllEntries" -#define GCONF_DBUS_DATABASE_GET_ALL_DIRS "AllDirs" -#define GCONF_DBUS_DATABASE_SET_SCHEMA "SetSchema" - -#define GCONF_DBUS_DATABASE_ADD_NOTIFY "AddNotify" -#define GCONF_DBUS_DATABASE_REMOVE_NOTIFY "RemoveNotify" +#define GCONF_DBUS_DATABASE_GET_ALL_DIRS "AllDirs" +#define GCONF_DBUS_DATABASE_SET_SCHEMA "SetSchema" +#define GCONF_DBUS_DATABASE_ADD_NOTIFY "AddNotify" +#define GCONF_DBUS_DATABASE_REMOVE_NOTIFY "RemoveNotify" -#define GCONF_DBUS_LISTENER_NOTIFY "Notify" - -#define GCONF_DBUS_CLIENT_SERVICE "org.gnome.GConf.ClientService" -#define GCONF_DBUS_CLIENT_OBJECT "/org/gnome/GConf/Client" -#define GCONF_DBUS_CLIENT_INTERFACE "org.gnome.GConf.Client" +#define GCONF_DBUS_LISTENER_NOTIFY "Notify" +#define GCONF_DBUS_CLIENT_SERVICE "org.gnome.GConf.ClientService" +#define GCONF_DBUS_CLIENT_OBJECT "/org/gnome/GConf/Client" +#define GCONF_DBUS_CLIENT_INTERFACE "org.gnome.GConf.Client" #define GCONF_DBUS_UNSET_INCLUDING_SCHEMA_NAMES 0x1 -#define GCONF_DBUS_ERROR_FAILED "org.gnome.GConf.Error.Failed" -#define GCONF_DBUS_ERROR_NO_PERMISSION "org.gnome.GConf.Error.NoPermission" -#define GCONF_DBUS_ERROR_BAD_ADDRESS "org.gnome.GConf.Error.BadAddress" -#define GCONF_DBUS_ERROR_BAD_KEY "org.gnome.GConf.Error.BadKey" -#define GCONF_DBUS_ERROR_PARSE_ERROR "org.gnome.GConf.Error.ParseError" -#define GCONF_DBUS_ERROR_CORRUPT "org.gnome.GConf.Error.Corrupt" -#define GCONF_DBUS_ERROR_TYPE_MISMATCH "org.gnome.GConf.Error.TypeMismatch" -#define GCONF_DBUS_ERROR_IS_DIR "org.gnome.GConf.Error.IsDir" -#define GCONF_DBUS_ERROR_IS_KEY "org.gnome.GConf.Error.IsKey" +#define GCONF_DBUS_ERROR_FAILED "org.gnome.GConf.Error.Failed" +#define GCONF_DBUS_ERROR_NO_PERMISSION "org.gnome.GConf.Error.NoPermission" +#define GCONF_DBUS_ERROR_BAD_ADDRESS "org.gnome.GConf.Error.BadAddress" +#define GCONF_DBUS_ERROR_BAD_KEY "org.gnome.GConf.Error.BadKey" +#define GCONF_DBUS_ERROR_PARSE_ERROR "org.gnome.GConf.Error.ParseError" +#define GCONF_DBUS_ERROR_CORRUPT "org.gnome.GConf.Error.Corrupt" +#define GCONF_DBUS_ERROR_TYPE_MISMATCH "org.gnome.GConf.Error.TypeMismatch" +#define GCONF_DBUS_ERROR_IS_DIR "org.gnome.GConf.Error.IsDir" +#define GCONF_DBUS_ERROR_IS_KEY "org.gnome.GConf.Error.IsKey" #define GCONF_DBUS_ERROR_NO_WRITABLE_DATABASE "org.gnome.GConf.Error.NoWritableDatabase" -#define GCONF_DBUS_ERROR_IN_SHUTDOWN "org.gnome.GConf.Error.InShutdown" -#define GCONF_DBUS_ERROR_OVERRIDDEN "org.gnome.GConf.Error.Overriden" -#define GCONF_DBUS_ERROR_LOCK_FAILED "org.gnome.GConf.Error.LockFailed" +#define GCONF_DBUS_ERROR_IN_SHUTDOWN "org.gnome.GConf.Error.InShutdown" +#define GCONF_DBUS_ERROR_OVERRIDDEN "org.gnome.GConf.Error.Overriden" +#define GCONF_DBUS_ERROR_LOCK_FAILED "org.gnome.GConf.Error.LockFailed" -#if 0 -#define GCONF_DBUS_ERROR_FAILED "Failed" -#define GCONF_DBUS_ERROR_NO_PERMISSION "NoPermission" -#define GCONF_DBUS_ERROR_BAD_ADDRESS "BadAddress" -#define GCONF_DBUS_ERROR_BAD_KEY "BadKey" -#define GCONF_DBUS_ERROR_PARSE_ERROR "ParseError" -#define GCONF_DBUS_ERROR_CORRUPT "Corrupt" -#define GCONF_DBUS_ERROR_TYPE_MISMATCH "TypeMismatch" -#define GCONF_DBUS_ERROR_IS_DIR "IsDir" -#define GCONF_DBUS_ERROR_IS_KEY "IsKey" -#define GCONF_DBUS_ERROR_NO_WRITABLE_DATABASE "NoWritableDatabase" -#define GCONF_DBUS_ERROR_IN_SHUTDOWN "InShutdown" -#define GCONF_DBUS_ERROR_OVERRIDDEN "Overriden" -#define GCONF_DBUS_ERROR_LOCK_FAILED "LockFailed" -#endif -void gconf_dbus_message_append_gconf_value (DBusMessage *message, - const GConfValue *value); -void gconf_dbus_message_iter_append_gconf_value (DBusMessageIter *iter, - const GConfValue *value); -GConfValue * gconf_dbus_create_gconf_value_from_message_iter (DBusMessageIter *iter); +void gconf_dbus_message_append_gconf_value (DBusMessage *message, + const GConfValue *value); +void gconf_dbus_message_iter_append_gconf_value (DBusMessageIter *iter, + const GConfValue *value); +GConfValue *gconf_dbus_create_gconf_value_from_message_iter (DBusMessageIter *iter); +void gconf_dbus_message_append_entry (DBusMessage *message, + const gchar *key, + const GConfValue *value, + gboolean is_default, + gboolean is_writable, + const gchar *schema_name); +gboolean gconf_dbus_get_entry_values_from_message_iter (DBusMessageIter *iter, + gchar **key, + GConfValue **value, + gboolean *is_default, + gboolean *is_writable, + gchar **schema_name); -void gconf_dbus_message_append_entry (DBusMessage *message, - const gchar *key, - const GConfValue *value, - gboolean is_default, - gboolean is_writable, - const gchar *schema_name); -gboolean gconf_dbus_get_entry_values_from_message_iter (DBusMessageIter *iter, - gchar **key, - GConfValue **value, - gboolean *is_default, - gboolean *is_writable, - gchar **schema_name); #endif/* GCONF_DBUS_UTILS_H */ diff --git a/gconf/gconf-dbus.c b/gconf/gconf-dbus.c index 770c48d1..89f96027 100644 --- a/gconf/gconf-dbus.c +++ b/gconf/gconf-dbus.c @@ -36,7 +36,7 @@ #include <unistd.h> #include <dbus/dbus.h> -#define d(x) +#define d(x) #define BUS_RULE "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus'" #define NOTIFY_RULE "type='method_call',interface='org.gnome.GConf.Database'" @@ -52,11 +52,16 @@ struct _GConfEngine { /* If non-NULL, this is a local engine; local engines don't do notification! */ GConfSources* local_sources; - - /* An address if this is not the default engine; + + /* A list of addresses that make up this db + * if this is not the default engine; * NULL if it's the default */ - gchar *address; + GSList *addresses; + + /* A concatentation of the addresses above. + */ + char *persistent_address; gpointer user_data; GDestroyNotify dnotify; @@ -137,7 +142,7 @@ static DBusHandlerResult gconf_dbus_message_filter (DBusConnection *dbus_conn, DBusMessage *message, gpointer user_data); -static GConfEngine *lookup_engine_by_address (const gchar *address); +static GConfEngine *lookup_engine_by_address (GSList *addresses); static GConfEngine *lookup_engine_by_database (const gchar *db); static gboolean gconf_handle_dbus_exception (DBusMessage *message, DBusError *derr, @@ -489,6 +494,10 @@ ensure_database (GConfEngine *conf, DBusMessage *message, *reply; DBusError error; gchar *db; + const char **strv; + int len, i; + GSList *list; + DBusMessageIter iter; g_return_val_if_fail (!conf->is_local, TRUE); @@ -520,11 +529,28 @@ ensure_database (GConfEngine *conf, GCONF_DBUS_SERVER_OBJECT, GCONF_DBUS_SERVER_INTERFACE, GCONF_DBUS_SERVER_GET_DB); - dbus_message_append_args (message, - DBUS_TYPE_STRING, conf->address, - DBUS_TYPE_INVALID); - } + dbus_message_append_iter_init (message, &iter); + + list = conf->addresses; + len = g_slist_length (list); + + strv = (const char **)g_new (char *, len + 1); + strv[len] = NULL; + + i = 0; + while (list) + { + strv[i] = (gchar *)list->data; + + list = list->next; + ++i; + } + + dbus_message_iter_append_string_array (&iter, strv, len); + g_free (strv); + } + dbus_error_init (&error); reply = dbus_connection_send_with_reply_and_block (global_conn, message, -1, &error); @@ -546,7 +572,7 @@ ensure_database (GConfEngine *conf, if (err) *err = gconf_error_new (GCONF_ERROR_BAD_ADDRESS, _("Server couldn't resolve the address `%s'"), - conf->address ? conf->address : "default"); + conf->persistent_address); return FALSE; } @@ -578,22 +604,30 @@ gconf_engine_is_local (GConfEngine* conf) static void register_engine (GConfEngine *conf) { - g_return_if_fail (conf->address != NULL); + g_return_if_fail (conf->addresses != NULL); + + g_assert (conf->persistent_address == NULL); + conf->persistent_address = + gconf_address_list_get_persistent_name (conf->addresses); + if (engines_by_address == NULL) engines_by_address = g_hash_table_new (g_str_hash, g_str_equal); - g_hash_table_insert (engines_by_address, conf->address, conf); + g_hash_table_insert (engines_by_address, conf->persistent_address, conf); } static void unregister_engine (GConfEngine *conf) { - g_return_if_fail (conf->address != NULL); g_return_if_fail (engines_by_address != NULL); - g_hash_table_remove (engines_by_address, conf->address); - + g_assert (conf->persistent_address != NULL); + + g_hash_table_remove (engines_by_address, conf->persistent_address); + g_free (conf->persistent_address); + conf->persistent_address = NULL; + if (g_hash_table_size (engines_by_address) == 0) { g_hash_table_destroy (engines_by_address); @@ -603,14 +637,24 @@ unregister_engine (GConfEngine *conf) } static GConfEngine * -lookup_engine_by_address (const gchar *address) +lookup_engine_by_address (GSList *addresses) { - if (engines_by_address) - return g_hash_table_lookup (engines_by_address, address); - else - return NULL; -} + if (engines_by_address != NULL) + { + GConfEngine *retval; + char *key; + + key = gconf_address_list_get_persistent_name (addresses); + + retval = g_hash_table_lookup (engines_by_address, key); + + g_free (key); + + return retval; + } + return NULL; +} /* * Connection maintenance @@ -747,6 +791,24 @@ gconf_engine_get_local (const gchar* address, return conf; } +GConfEngine * +gconf_engine_get_local_for_addresses (GSList *addresses, + GError **err) +{ + GConfEngine *conf; + + g_return_val_if_fail (addresses != NULL, NULL); + g_return_val_if_fail (err == NULL || *err == NULL, NULL); + + conf = gconf_engine_blank (FALSE); + + conf->local_sources = gconf_sources_new_from_addresses (addresses, err); + + g_assert (gconf_engine_is_local (conf)); + + return conf; +} + GConfEngine* gconf_engine_get_default (void) { @@ -770,18 +832,22 @@ gconf_engine_get_default (void) } GConfEngine* -gconf_engine_get_for_address (const gchar* address, GError** err) +gconf_engine_get_for_address (const gchar *address, + GError **err) { - GConfEngine* conf; + GConfEngine *conf; + GSList *addresses; - conf = lookup_engine_by_address (address); + addresses = g_slist_append (NULL, g_strdup (address)); + + conf = lookup_engine_by_address (addresses); if (conf == NULL) { conf = gconf_engine_blank (TRUE); conf->is_default = FALSE; - conf->address = g_strdup (address); + conf->addresses = addresses; if (!ensure_database (conf, TRUE, err)) { @@ -792,6 +858,48 @@ gconf_engine_get_for_address (const gchar* address, GError** err) register_engine (conf); } else + { + g_free (addresses->data); + g_slist_free (addresses); + conf->refcount += 1; + } + + return conf; +} + +GConfEngine* +gconf_engine_get_for_addresses (GSList *addresses, GError** err) +{ + GConfEngine* conf; + + conf = lookup_engine_by_address (addresses); + + if (conf == NULL) + { + GSList *tmp; + + conf = gconf_engine_blank (TRUE); + + conf->is_default = FALSE; + conf->addresses = NULL; + + tmp = addresses; + while (tmp != NULL) + { + conf->addresses = g_slist_append (conf->addresses, + g_strdup (tmp->data)); + tmp = tmp->next; + } + + if (!ensure_database (conf, TRUE, err)) + { + gconf_engine_unref (conf); + return NULL; + } + + register_engine (conf); + } + else conf->refcount += 1; return conf; @@ -833,10 +941,16 @@ gconf_engine_unref (GConfEngine* conf) (* conf->dnotify) (conf->user_data); } - /* do this after removing the notifications, - to avoid funky race conditions */ - if (conf->address) - unregister_engine (conf); + if (conf->addresses) + { + gconf_address_list_free (conf->addresses); + conf->addresses = NULL; + } + + if (conf->persistent_address) + { + unregister_engine (conf); + } /* Release the ConfigDatabase */ gconf_engine_detach (conf); @@ -1248,7 +1362,7 @@ gconf_engine_set (GConfEngine* conf, const gchar* key, { GError* error = NULL; - gconf_sources_set_value (conf->local_sources, key, value, &error); + gconf_sources_set_value (conf->local_sources, key, value, NULL, &error); if (error != NULL) { @@ -1320,7 +1434,7 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err) { GError* error = NULL; - gconf_sources_unset_value (conf->local_sources, key, NULL, &error); + gconf_sources_unset_value (conf->local_sources, key, NULL, NULL, &error); if (error != NULL) { @@ -1354,7 +1468,7 @@ gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err) dbus_message_append_args (message, DBUS_TYPE_STRING, key, - DBUS_TYPE_STRING, gconf_current_locale (), + DBUS_TYPE_STRING, "", DBUS_TYPE_INVALID); dbus_error_init (&error); @@ -1447,7 +1561,7 @@ gconf_engine_recursive_unset (GConfEngine *conf, dbus_message_append_args (message, DBUS_TYPE_STRING, key, - DBUS_TYPE_STRING, gconf_current_locale (), + DBUS_TYPE_STRING, "", DBUS_TYPE_UINT32, dbus_flags, DBUS_TYPE_INVALID); @@ -2150,7 +2264,7 @@ gconf_debug_shutdown (void) { gconf_detach_config_server (); - return 1; + return 0; } static DBusHandlerResult diff --git a/gconf/gconf-engine.h b/gconf/gconf-engine.h index 692d1155..8658270d 100644 --- a/gconf/gconf-engine.h +++ b/gconf/gconf-engine.h @@ -36,11 +36,16 @@ GConfEngine* gconf_engine_get_default (void); /* returns NULL on error; requests single specified source */ GConfEngine* gconf_engine_get_for_address (const gchar* address, GError** err); +GConfEngine* gconf_engine_get_for_addresses (GSList *addresses, + GError** err); void gconf_engine_unref (GConfEngine* conf); void gconf_engine_ref (GConfEngine* conf); #ifdef GCONF_ENABLE_INTERNALS -GConfEngine* gconf_engine_get_local (const gchar* address, GError** err); +GConfEngine *gconf_engine_get_local (const char *address, + GError **err); +GConfEngine *gconf_engine_get_local_for_addresses (GSList *addresses, + GError **err); #endif /* For use by language bindings only, will be deprecated in GNOME 2.0 diff --git a/gconf/gconf-internals.c b/gconf/gconf-internals.c index 3352d9bf..f2238794 100644 --- a/gconf/gconf-internals.c +++ b/gconf/gconf-internals.c @@ -420,6 +420,84 @@ gconf_load_source_path(const gchar* filename, GError** err) return l; } +char * +gconf_address_list_get_persistent_name (GSList *addresses) +{ + GSList *tmp; + GString *str = NULL; + + if (!addresses) + { + return g_strdup ("empty"); + } + + tmp = addresses; + while (tmp != NULL) + { + const char *address = tmp->data; + + if (str == NULL) + { + str = g_string_new (address); + } + else + { + g_string_append_c (str, GCONF_DATABASE_LIST_DELIM); + g_string_append (str, address); + } + + tmp = tmp->next; + } + + return g_string_free (str, FALSE); +} + +GSList * +gconf_persistent_name_get_address_list (const char *persistent_name) +{ + char delim [2] = { GCONF_DATABASE_LIST_DELIM, '\0' }; + char **address_vector; + + address_vector = g_strsplit (persistent_name, delim, -1); + if (address_vector != NULL) + { + GSList *retval = NULL; + int i; + + i = 0; + while (address_vector [i] != NULL) + { + retval = g_slist_append (retval, g_strdup (address_vector [i])); + ++i; + } + + g_strfreev (address_vector); + + return retval; + } + else + { + return g_slist_append (NULL, g_strdup (persistent_name)); + } +} + +void +gconf_address_list_free (GSList *addresses) +{ + GSList *tmp; + + tmp = addresses; + while (tmp != NULL) + { + g_free (tmp->data); + tmp = tmp->next; + } + + g_slist_free (addresses); +} + + + /* This should also support concatting filesystem dirs and keys, or dir and subdir. */ diff --git a/gconf/gconf-internals.h b/gconf/gconf-internals.h index 626415bb..79179a47 100644 --- a/gconf/gconf-internals.h +++ b/gconf/gconf-internals.h @@ -38,6 +38,8 @@ #include "gconf-engine.h" #include "gconf-sources.h" +#define GCONF_DATABASE_LIST_DELIM ';' + gchar* gconf_key_directory (const gchar* key); const gchar* gconf_key_key (const gchar* key); @@ -52,6 +54,10 @@ enum { gboolean gconf_file_test (const gchar* filename, int test); gboolean gconf_file_exists (const gchar* filename); +char *gconf_address_list_get_persistent_name (GSList *addresses); +GSList *gconf_persistent_name_get_address_list (const char *persistent_name); +void gconf_address_list_free (GSList *addresses); + const gchar* gconf_value_type_to_string (GConfValueType type); GConfValueType gconf_value_type_from_string (const gchar *str); diff --git a/gconf/gconf-sources.c b/gconf/gconf-sources.c index 0962c4bd..2245d9e9 100644 --- a/gconf/gconf-sources.c +++ b/gconf/gconf-sources.c @@ -77,8 +77,8 @@ gconf_source_free (GConfSource* source) g_return_if_fail(source != NULL); backend = source->backend; - - (*source->backend->vtable->destroy_source)(source); + + (*source->backend->vtable.destroy_source)(source); /* Remove ref held by the source. */ gconf_backend_unref(backend); @@ -86,8 +86,8 @@ gconf_source_free (GConfSource* source) #define SOURCE_READABLE(source, key, err) \ ( ((source)->flags & GCONF_SOURCE_ALL_READABLE) || \ - ((source)->backend->vtable->readable != NULL && \ - (*(source)->backend->vtable->readable)((source), (key), (err))) ) + ((source)->backend->vtable.readable != NULL && \ + (*(source)->backend->vtable.readable)((source), (key), (err))) ) static gboolean source_is_writable(GConfSource* source, const gchar* key, GError** err) @@ -96,8 +96,8 @@ source_is_writable(GConfSource* source, const gchar* key, GError** err) return FALSE; else if ((source->flags & GCONF_SOURCE_ALL_WRITEABLE) != 0) return TRUE; - else if ((source->backend->vtable->writable != NULL) && - (*source->backend->vtable->writable)(source, key, err)) + else if ((source->backend->vtable.writable != NULL) && + (*source->backend->vtable.writable)(source, key, err)) return TRUE; else return FALSE; @@ -119,7 +119,7 @@ gconf_source_query_value (GConfSource* source, if ( SOURCE_READABLE(source, key, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, NULL); - return (*source->backend->vtable->query_value)(source, key, locales, schema_name, err); + return (*source->backend->vtable.query_value)(source, key, locales, schema_name, err); } else return NULL; @@ -139,7 +139,7 @@ gconf_source_query_metainfo (GConfSource* source, if ( SOURCE_READABLE(source, key, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, NULL); - return (*source->backend->vtable->query_metainfo)(source, key, err); + return (*source->backend->vtable.query_metainfo)(source, key, err); } else return NULL; @@ -163,7 +163,7 @@ gconf_source_set_value (GConfSource* source, if ( source_is_writable(source, key, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, FALSE); - (*source->backend->vtable->set_value)(source, key, value, err); + (*source->backend->vtable.set_value)(source, key, value, err); return TRUE; } else @@ -184,7 +184,7 @@ gconf_source_unset_value (GConfSource* source, { g_return_val_if_fail(err == NULL || *err == NULL, FALSE); - (*source->backend->vtable->unset_value)(source, key, locale, err); + (*source->backend->vtable.unset_value)(source, key, locale, err); return TRUE; } else @@ -204,7 +204,7 @@ gconf_source_all_entries (GConfSource* source, if ( SOURCE_READABLE(source, dir, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, NULL); - return (*source->backend->vtable->all_entries)(source, dir, locales, err); + return (*source->backend->vtable.all_entries)(source, dir, locales, err); } else return NULL; @@ -222,7 +222,7 @@ gconf_source_all_dirs (GConfSource* source, if ( SOURCE_READABLE(source, dir, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, NULL); - return (*source->backend->vtable->all_subdirs)(source, dir, err); + return (*source->backend->vtable.all_subdirs)(source, dir, err); } else return NULL; @@ -240,7 +240,7 @@ gconf_source_dir_exists (GConfSource* source, if ( SOURCE_READABLE(source, dir, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, FALSE); - return (*source->backend->vtable->dir_exists)(source, dir, err); + return (*source->backend->vtable.dir_exists)(source, dir, err); } else return FALSE; @@ -258,7 +258,7 @@ gconf_source_remove_dir (GConfSource* source, if ( source_is_writable(source, dir, err) ) { g_return_if_fail(err == NULL || *err == NULL); - (*source->backend->vtable->remove_dir)(source, dir, err); + (*source->backend->vtable.remove_dir)(source, dir, err); } } @@ -275,7 +275,7 @@ gconf_source_set_schema (GConfSource* source, if ( source_is_writable(source, key, err) ) { g_return_val_if_fail(err == NULL || *err == NULL, FALSE); - (*source->backend->vtable->set_schema)(source, key, schema_key, err); + (*source->backend->vtable.set_schema)(source, key, schema_key, err); return TRUE; } else @@ -285,7 +285,47 @@ gconf_source_set_schema (GConfSource* source, static gboolean gconf_source_sync_all (GConfSource* source, GError** err) { - return (*source->backend->vtable->sync_all)(source, err); + return (*source->backend->vtable.sync_all)(source, err); +} + +static void +gconf_source_set_notify_func (GConfSource *source, + GConfSourceNotifyFunc notify_func, + gpointer user_data) +{ + g_return_if_fail (source != NULL); + + if (source->backend->vtable.set_notify_func) + { + (*source->backend->vtable.set_notify_func) (source, notify_func, user_data); + } +} + +static void +gconf_source_add_listener (GConfSource *source, + guint id, + const gchar *namespace_section) +{ + g_return_if_fail (source != NULL); + g_return_if_fail (id > 0); + + if (source->backend->vtable.add_listener) + { + (*source->backend->vtable.add_listener) (source, id, namespace_section); + } +} + +static void +gconf_source_remove_listener (GConfSource *source, + guint id) +{ + g_return_if_fail (source != NULL); + g_return_if_fail (id > 0); + + if (source->backend->vtable.remove_listener) + { + (*source->backend->vtable.remove_listener) (source, id); + } } /* @@ -378,7 +418,8 @@ gconf_sources_new_from_source (GConfSource* source) sources = g_new0(GConfSources, 1); - sources->sources = g_list_append(NULL, source); + if (source) + sources->sources = g_list_append(NULL, source); return sources; } @@ -413,8 +454,8 @@ gconf_sources_clear_cache (GConfSources *sources) { GConfSource* source = tmp->data; - if (source->backend->vtable->clear_cache) - (*source->backend->vtable->clear_cache)(source); + if (source->backend->vtable.clear_cache) + (*source->backend->vtable.clear_cache)(source); tmp = g_list_next(tmp); } @@ -623,6 +664,7 @@ void gconf_sources_set_value (GConfSources* sources, const gchar* key, const GConfValue* value, + GConfSources **modified_sources, GError** err) { GList* tmp; @@ -630,6 +672,9 @@ gconf_sources_set_value (GConfSources* sources, g_return_if_fail(sources != NULL); g_return_if_fail(key != NULL); g_return_if_fail((err == NULL) || (*err == NULL)); + + if (modified_sources) + *modified_sources = NULL; if (!gconf_key_check(key, err)) return; @@ -659,7 +704,11 @@ gconf_sources_set_value (GConfSources* sources, { /* source was writable, err may be set */ gconf_log (GCL_DEBUG, "%s was writable in %s", key, src->address); - return; + if (modified_sources) + { + *modified_sources = gconf_sources_new_from_source (src); + } + return; } else { @@ -697,6 +746,7 @@ void gconf_sources_unset_value (GConfSources* sources, const gchar* key, const gchar* locale, + GConfSources **modified_sources, GError** err) { /* We unset in every layer we can write to... */ @@ -728,12 +778,43 @@ gconf_sources_unset_value (GConfSources* sources, return; } } + + if (modified_sources) + { + if (*modified_sources == NULL) + { + *modified_sources = gconf_sources_new_from_source (src); + } + else + { + (*modified_sources)->sources = + g_list_prepend ((*modified_sources)->sources, src); + } + } } tmp = g_list_next(tmp); } } +static GSList * +prepend_unset_notify (GSList *notifies, + GConfSources *modified_sources, + char *key) +{ + GConfUnsetNotify *notify; + + g_assert (modified_sources != NULL); + g_assert (key != NULL); + + notify = g_new0 (GConfUnsetNotify, 1); + + notify->modified_sources = modified_sources; + notify->key = key; + + return g_slist_append (notifies, notify); +} + static void recursive_unset_helper (GConfSources *sources, const char *key, @@ -747,6 +828,14 @@ recursive_unset_helper (GConfSources *sources, GSList* entries; GSList* tmp; const char *locales[2] = { NULL, NULL }; + GConfSources* modified_sources; + GConfSources** modifiedp = NULL; + + if (notifies) + { + modified_sources = NULL; + modifiedp = &modified_sources; + } err = NULL; @@ -809,16 +898,20 @@ recursive_unset_helper (GConfSources *sources, while (tmp != NULL) { GConfEntry* entry = tmp->data; - char *full = gconf_concat_dir_and_key (key, - gconf_entry_get_key (entry)); + char *full, *freeme; + + full = freeme = gconf_concat_dir_and_key (key, + gconf_entry_get_key (entry)); - if (notifies) - *notifies = g_slist_prepend (*notifies, g_strdup (full)); - gconf_sources_unset_value (sources, - full, - locale, - &err); + gconf_sources_unset_value (sources, full, locale, modifiedp, &err); + if (notifies) + { + *notifies = prepend_unset_notify (*notifies, modified_sources, full); + modified_sources = NULL; + freeme = NULL; + } + if (err != NULL) { gconf_log (GCL_DEBUG, "Error unsetting '%s': %s\n", @@ -850,7 +943,7 @@ recursive_unset_helper (GConfSources *sources, } gconf_entry_free (entry); - g_free (full); + g_free (freeme); tmp = g_slist_next (tmp); } @@ -858,10 +951,14 @@ recursive_unset_helper (GConfSources *sources, g_slist_free (entries); } + gconf_sources_unset_value (sources, key, locale, modifiedp, &err); if (notifies) - *notifies = g_slist_prepend (*notifies, g_strdup (key)); - - gconf_sources_unset_value (sources, key, locale, &err); + { + *notifies = prepend_unset_notify (*notifies, + modified_sources, + g_strdup (key)); + modified_sources = NULL; + } if (err != NULL) { @@ -895,7 +992,28 @@ gconf_sources_recursive_unset (GConfSources *sources, notifies, &first_error); if (first_error) - g_propagate_error (err, first_error); + { + if (notifies != NULL && *notifies != NULL) + { + GSList *tmp; + + tmp = *notifies; + while (tmp != NULL) + { + GConfUnsetNotify *notify = tmp->data; + + g_free (notify->key); + g_free (notify); + + tmp = tmp->next; + } + + g_slist_free (*notifies); + *notifies = NULL; + } + + g_propagate_error (err, first_error); + } } gboolean @@ -1550,3 +1668,118 @@ gconf_sources_query_default_value(GConfSources* sources, return NULL; } } + +void +gconf_sources_set_notify_func (GConfSources *sources, + GConfSourceNotifyFunc notify_func, + gpointer user_data) +{ + GList *tmp; + + tmp = sources->sources; + while (tmp != NULL) + { + gconf_source_set_notify_func (tmp->data, notify_func, user_data); + + tmp = tmp->next; + } +} + +void +gconf_sources_add_listener (GConfSources *sources, + guint id, + const gchar *namespace_section) +{ + GList *tmp; + + tmp = sources->sources; + while (tmp != NULL) + { + gconf_source_add_listener (tmp->data, id, namespace_section); + + tmp = tmp->next; + } +} + +void +gconf_sources_remove_listener (GConfSources *sources, + guint id) +{ + GList *tmp; + + tmp = sources->sources; + while (tmp != NULL) + { + gconf_source_remove_listener (tmp->data, id); + + tmp = tmp->next; + } +} + +/* Non-allocating variant of gconf_address_resource() + */ +static const char * +get_address_resource (const char *address) +{ + const char *start; + + g_return_val_if_fail (address != NULL, NULL); + + start = strchr (address, ':'); + if (start != NULL) + { + start = strchr (++start, ':'); + + if (start != NULL) + start++; + } + + return start; +} + +/* Return TRUE if + * 1. @sources contains @modified_src and + * 2. @key is not set in any source above @modified_src. + */ +gboolean +gconf_sources_is_affected (GConfSources *sources, + GConfSource *modified_src, + const char *key) +{ + const char *modified_resource; + GList *tmp; + + modified_resource = get_address_resource (modified_src->address); + + tmp = sources->sources; + while (tmp != NULL) + { + GConfSource *source = tmp->data; + + if (source->backend == modified_src->backend && + strcmp (modified_resource, get_address_resource (source->address)) == 0) + break; + + tmp = tmp->next; + } + + if (tmp) + { + tmp = tmp->prev; + while (tmp != NULL) + { + GConfValue *val; + + val = gconf_source_query_value (tmp->data, key, NULL, NULL, NULL); + if (val != NULL) + { + gconf_value_free (val); + return FALSE; + } + + tmp = tmp->prev; + } + } + + return TRUE; +} diff --git a/gconf/gconf-sources.h b/gconf/gconf-sources.h index a8966414..abee387a 100644 --- a/gconf/gconf-sources.h +++ b/gconf/gconf-sources.h @@ -24,6 +24,7 @@ #include <glib.h> #include "gconf-error.h" #include "gconf-value.h" +#include "gconf-listeners.h" /* Sources are not interchangeable; different backend engines will return * GConfSource with different private elements. @@ -50,6 +51,10 @@ typedef enum { GCONF_SOURCE_ALL_FLAGS = ((1 << 0) | (1 << 1)) } GConfSourceFlags; +typedef void (* GConfSourceNotifyFunc) (GConfSource *source, + const gchar *location, + gpointer user_data); + GConfSource* gconf_resolve_address (const gchar* address, GError** err); @@ -60,9 +65,15 @@ typedef struct _GConfSources GConfSources; struct _GConfSources { GList* sources; - }; +typedef struct +{ + GConfSources *modified_sources; + char *key; +} GConfUnsetNotify; + + /* Even on error, this gives you an empty source list, i.e. never returns NULL but may set the error if some addresses weren't resolved and may contain no sources. */ @@ -82,10 +93,12 @@ GConfValue* gconf_sources_query_value (GConfSources *sources, void gconf_sources_set_value (GConfSources *sources, const gchar *key, const GConfValue *value, + GConfSources **modified_sources, GError **err); void gconf_sources_unset_value (GConfSources *sources, const gchar *key, const gchar *locale, + GConfSources **modified_sources, GError **err); void gconf_sources_recursive_unset (GConfSources *sources, const gchar *key, @@ -124,11 +137,17 @@ GConfValue* gconf_sources_query_default_value(GConfSources* sources, gboolean* is_writable, GError** err); -#endif - - - - - +void gconf_sources_set_notify_func (GConfSources *sources, + GConfSourceNotifyFunc notify_func, + gpointer user_data); +void gconf_sources_add_listener (GConfSources *sources, + guint id, + const gchar *location); +void gconf_sources_remove_listener (GConfSources *sources, + guint id); +gboolean gconf_sources_is_affected (GConfSources *sources, + GConfSource *modified_src, + const char *key); +#endif diff --git a/gconf/gconf.h b/gconf/gconf.h index 284c05b6..a5a28699 100644 --- a/gconf/gconf.h +++ b/gconf/gconf.h @@ -29,8 +29,6 @@ G_BEGIN_DECLS #include <gconf/gconf-error.h> #include <gconf/gconf-enum-types.h> -//typedef struct _GConfEngine GConfEngine; - typedef void (*GConfNotifyFunc) (GConfEngine* conf, guint cnxn_id, GConfEntry *entry, diff --git a/gconf/gconfd-corba.c b/gconf/gconfd-corba.c index 31849808..392e2f8b 100644 --- a/gconf/gconfd-corba.c +++ b/gconf/gconfd-corba.c @@ -48,7 +48,7 @@ static void log_clients_to_string (GString *str); * CORBA goo */ -static ConfigServer server = CORBA_OBJECT_NIL; +static ConfigServer2 server = CORBA_OBJECT_NIL; static PortableServer_POA the_poa; static ConfigDatabase @@ -60,6 +60,11 @@ gconfd_get_database(PortableServer_Servant servant, const CORBA_char* address, CORBA_Environment* ev); +static ConfigDatabase +gconfd_get_database_for_addresses (PortableServer_Servant servant, + const ConfigServer2_AddressList *addresses, + CORBA_Environment *ev); + static void gconfd_add_client (PortableServer_Servant servant, const ConfigListener client, @@ -92,8 +97,13 @@ static POA_ConfigServer__epv server_epv = { gconfd_shutdown }; -static POA_ConfigServer__vepv poa_server_vepv = { &base_epv, &server_epv }; -static POA_ConfigServer poa_server_servant = { NULL, &poa_server_vepv }; +static POA_ConfigServer2__epv server2_epv = { + NULL, + gconfd_get_database_for_addresses +}; + +static POA_ConfigServer2__vepv poa_server_vepv = { &base_epv, &server_epv, &server2_epv }; +static POA_ConfigServer2 poa_server_servant = { NULL, &poa_server_vepv }; static ConfigDatabase gconfd_get_default_database(PortableServer_Servant servant, @@ -118,19 +128,51 @@ gconfd_get_database(PortableServer_Servant servant, CORBA_Environment* ev) { GConfDatabase *db; + GSList *addresses; GError* error = NULL; if (gconfd_corba_check_in_shutdown (ev)) return CORBA_OBJECT_NIL; - db = gconfd_obtain_database (address, &error); - + addresses = g_slist_append (NULL, (char *) address); + db = gconfd_obtain_database (addresses, &error); + g_slist_free (addresses); + if (db != NULL) return CORBA_Object_duplicate (gconf_database_corba_get_objref (db), ev); - else if (gconf_corba_set_exception(&error, ev)) - return CORBA_OBJECT_NIL; - else + + gconf_corba_set_exception (&error, ev); + + return CORBA_OBJECT_NIL; +} + +static ConfigDatabase +gconfd_get_database_for_addresses (PortableServer_Servant servant, + const ConfigServer2_AddressList *seq, + CORBA_Environment *ev) +{ + GConfDatabase *db; + GSList *addresses = NULL; + GError *error = NULL; + int i; + + if (gconfd_corba_check_in_shutdown (ev)) return CORBA_OBJECT_NIL; + + i = 0; + while (i < seq->_length) + addresses = g_slist_append (addresses, seq->_buffer [i++]); + + db = gconfd_obtain_database (addresses, &error); + + g_slist_free (addresses); + + if (db != NULL) + return CORBA_Object_duplicate (gconf_database_corba_get_objref (db), ev); + + gconf_corba_set_exception (&error, ev); + + return CORBA_OBJECT_NIL; } static void @@ -176,7 +218,7 @@ gconfd_shutdown(PortableServer_Servant servant, CORBA_Environment *ev) } PortableServer_POA -gconf_corba_get_poa () +gconf_corba_get_poa (void) { return the_poa; } @@ -192,7 +234,7 @@ gconfd_corba_init (void) orb = gconf_orb_get (); - POA_ConfigServer__init (&poa_server_servant, &ev); + POA_ConfigServer2__init (&poa_server_servant, &ev); the_poa = (PortableServer_POA)CORBA_ORB_resolve_initial_references(orb, "RootPOA", &ev); PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(the_poa, &ev), &ev); @@ -337,7 +379,7 @@ close_append_handle (void) * leave the running log in place. */ void -gconfd_corba_logfile_save (void) +gconfd_corba_logfile_save (GConfDatabase *default_db) { GList *tmp_list; gchar *logdir = NULL; @@ -346,7 +388,7 @@ gconfd_corba_logfile_save (void) gchar *tmpfile2 = NULL; GString *saveme = NULL; gint fd = -1; - + /* Close the running log */ close_append_handle (); @@ -356,18 +398,12 @@ gconfd_corba_logfile_save (void) * that matter on open() */ - saveme = g_string_new (""); + saveme = g_string_new (NULL); /* Clients */ log_clients_to_string (saveme); - /* Default database */ - gconf_database_log_listeners_to_string (gconfd_lookup_database (NULL), - TRUE, - saveme); - - /* Other databases */ - + /* Databases */ tmp_list = gconfd_get_database_list ();; while (tmp_list) @@ -375,7 +411,7 @@ gconfd_corba_logfile_save (void) GConfDatabase *db = tmp_list->data; gconf_database_log_listeners_to_string (db, - FALSE, + db == default_db ? TRUE : FALSE, saveme); tmp_list = g_list_next (tmp_list); @@ -906,13 +942,21 @@ listener_logentry_restore_and_destroy_foreach (gpointer key, gpointer data) { ListenerLogEntry *lle = key; - GConfDatabase *db; + GConfDatabase *db = NULL; if (strcmp (lle->address, "def") == 0) db = gconfd_lookup_database (NULL); else - db = gconfd_obtain_database (lle->address, NULL); - + { + GSList *addresses; + + addresses = gconf_persistent_name_get_address_list (lle->address); + + db = gconfd_obtain_database (addresses, NULL); + + gconf_address_list_free (addresses); + } + if (db == NULL) { gconf_log (GCL_WARNING, @@ -948,7 +992,7 @@ read_line (FILE *f) int c; GString *str; - str = g_string_new (""); + str = g_string_new (NULL); flockfile (f); diff --git a/gconf/gconfd-corba.h b/gconf/gconfd-corba.h index 2eb080e1..f5578d60 100644 --- a/gconf/gconfd-corba.h +++ b/gconf/gconfd-corba.h @@ -49,7 +49,7 @@ gboolean gconfd_logfile_change_listener (GConfDatabase *db, const gchar *where, GError **err); -void gconfd_corba_logfile_save (void); +void gconfd_corba_logfile_save (GConfDatabase *default_db); void gconfd_corba_logfile_read (void); void gconfd_corba_log_client_add (const ConfigListener client); void gconfd_corba_log_client_remove (const ConfigListener client); diff --git a/gconf/gconfd-dbus.c b/gconf/gconfd-dbus.c index 0c569ed2..528282f5 100644 --- a/gconf/gconfd-dbus.c +++ b/gconf/gconfd-dbus.c @@ -1,3 +1,4 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ /* GConf * Copyright (C) 2003 Imendio HB * @@ -26,7 +27,7 @@ static DBusConnection *bus_conn; static const char *server_path[] = { "org", "gnome", "GConf", "Server", NULL }; -static gint nr_of_connections = 0; +static int nr_of_connections = 0; #define SERVICE_DELETED_RULE "type='signal',member='ServiceDeleted'," \ "sender='org.freedesktop.DBus',interface='org.freedesktop.DBus'" @@ -54,7 +55,6 @@ server_vtable = { static void server_unregistered_func (DBusConnection *connection, void *user_data) { - g_print ("Server object unregistered\n"); nr_of_connections = 0; } @@ -101,17 +101,17 @@ server_message_func (DBusConnection *connection, static void server_real_handle_get_db (DBusConnection *connection, DBusMessage *message, - const char *address) + GSList *addresses) { DBusMessageIter iter; GConfDatabaseDBus *db; DBusMessage *reply; GError *gerror = NULL; - + if (gconfd_dbus_check_in_shutdown (connection, message)) return; - db = gconf_database_dbus_get (connection, address, &gerror); + db = gconf_database_dbus_get (connection, addresses, &gerror); if (gconfd_dbus_set_exception (connection, message, &gerror)) return; @@ -142,15 +142,44 @@ server_handle_get_default_db (DBusConnection *connection, static void server_handle_get_db (DBusConnection *connection, DBusMessage *message) { - char *address; + GSList *addresses = NULL; + char *address; + DBusMessageIter iter; + DBusMessageIter array_iter; + int array_type; + DBusMessage *reply; - if (!gconfd_dbus_get_message_args (connection, message, - DBUS_TYPE_STRING, &address, - 0)) - return; + if (!dbus_message_iter_init (message, &iter)) + goto fail; + + if (!dbus_message_iter_init_array_iterator (&iter, + &array_iter, + &array_type) || + array_type != DBUS_TYPE_STRING) + goto fail; + + while (1) + { + address = dbus_message_iter_get_string (&array_iter); + + addresses = g_slist_append (addresses, address); + + if (!dbus_message_iter_next (&array_iter)) + break; + } + + server_real_handle_get_db (connection, message, addresses); + + g_slist_foreach (addresses, (GFunc)dbus_free, NULL); + g_slist_free (addresses); - server_real_handle_get_db (connection, message, address); - dbus_free (address); + return; + + fail: + reply = dbus_message_new_error (message, GCONF_DBUS_ERROR_FAILED, + _("Got a malformed message.")); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); } static void @@ -190,14 +219,6 @@ gconfd_dbus_init (void) return FALSE; } - if (!dbus_bus_register (bus_conn, &error)) - { - gconf_log (GCL_ERR, _("Failed to register client with the D-BUS bus daemon: %s"), - error.message); - dbus_error_free (&error); - return FALSE; - } - /* Add filter for ServiceDeleted so we get notified when the clients go away. */ dbus_bus_add_match (bus_conn, SERVICE_DELETED_RULE, NULL); diff --git a/gconf/gconfd.c b/gconf/gconfd.c index 3550232c..83925718 100644 --- a/gconf/gconfd.c +++ b/gconf/gconfd.c @@ -44,6 +44,7 @@ #ifdef HAVE_DBUS #include "gconfd-dbus.h" +#include "gconf-database-dbus.h" #endif #include <stdio.h> @@ -85,6 +86,10 @@ safe_g_hash_table_insert(GHashTable* ht, gpointer key, gpointer value) static GConfLock *daemon_lock = NULL; +static GList* db_list = NULL; +static GHashTable* dbs_by_addresses = NULL; +static GConfDatabase *default_db = NULL; + /* * Declarations */ @@ -92,9 +97,7 @@ static GConfLock *daemon_lock = NULL; static void gconf_main (void); static gboolean gconf_main_is_running (void); - - -static void enter_shutdown (void); +static void enter_shutdown (void); static void init_databases (void); static void shutdown_databases (void); @@ -568,7 +571,7 @@ main(int argc, char** argv) /* Save current state in logfile (may compress the logfile a good * bit) */ - gconfd_corba_logfile_save (); + gconfd_corba_logfile_save (default_db); #endif shutdown_databases (); @@ -648,7 +651,7 @@ periodic_cleanup_timeout(gpointer data) #ifdef HAVE_ORBIT /* Compress the running state file */ - gconfd_corba_logfile_save (); + gconfd_corba_logfile_save (default_db); #endif need_log_cleanup = FALSE; @@ -714,23 +717,15 @@ gconf_main_is_running (void) * Database storage */ -static GList* db_list = NULL; -static GHashTable* dbs_by_address = NULL; -static GConfDatabase *default_db = NULL; - static void init_databases (void) { gconfd_need_log_cleanup (); g_assert(db_list == NULL); - g_assert(dbs_by_address == NULL); - - dbs_by_address = g_hash_table_new (g_str_hash, g_str_equal); - - /* Default database isn't in the address hash since it has - multiple addresses in a stack - */ + g_assert(dbs_by_addresses == NULL); + + dbs_by_addresses = g_hash_table_new (g_str_hash, g_str_equal); } static void @@ -739,10 +734,8 @@ set_default_database (GConfDatabase* db) gconfd_need_log_cleanup (); default_db = db; - - /* Default database isn't in the address hash since it has - multiple addresses in a stack - */ + + register_database (db); } static void @@ -751,9 +744,9 @@ register_database (GConfDatabase *db) gconfd_need_log_cleanup (); if (db->sources->sources) - safe_g_hash_table_insert(dbs_by_address, - ((GConfSource*)db->sources->sources->data)->address, - db); + safe_g_hash_table_insert (dbs_by_addresses, + (char *) gconf_database_get_persistent_name (db), + db); db_list = g_list_prepend (db_list, db); } @@ -764,8 +757,10 @@ unregister_database (GConfDatabase *db) gconfd_need_log_cleanup (); if (db->sources->sources) - g_hash_table_remove(dbs_by_address, - ((GConfSource*)(db->sources->sources->data))->address); + { + g_hash_table_remove (dbs_by_addresses, + gconf_database_get_persistent_name (db)); + } db_list = g_list_remove (db_list, db); @@ -773,12 +768,21 @@ unregister_database (GConfDatabase *db) } GConfDatabase* -gconfd_lookup_database (const gchar *address) +gconfd_lookup_database (GSList *addresses) { - if (address == NULL) + GConfDatabase *retval; + char *key; + + if (addresses == NULL) return default_db; - else - return g_hash_table_lookup (dbs_by_address, address); + + key = gconf_address_list_get_persistent_name (addresses); + + retval = g_hash_table_lookup (dbs_by_addresses, key); + + g_free (key); + + return retval; } GList * @@ -788,23 +792,19 @@ gconfd_get_database_list (void) } GConfDatabase* -gconfd_obtain_database (const gchar *address, +gconfd_obtain_database (GSList *addresses, GError **err) { - GConfSources* sources; - GSList* addresses = NULL; GError* error = NULL; GConfDatabase *db; - db = gconfd_lookup_database (address); + db = gconfd_lookup_database (addresses); if (db) return db; - addresses = g_slist_append(addresses, g_strdup(address)); sources = gconf_sources_new_from_addresses(addresses, &error); - g_slist_free (addresses); if (error != NULL) { @@ -865,7 +865,7 @@ drop_old_databases(void) GConfDatabase* db = tmp_list->data; unregister_database (db); - + tmp_list = g_list_next (tmp_list); } @@ -895,10 +895,10 @@ shutdown_databases (void) g_list_free (db_list); db_list = NULL; - if (dbs_by_address) - g_hash_table_destroy(dbs_by_address); + if (dbs_by_addresses) + g_hash_table_destroy(dbs_by_addresses); - dbs_by_address = NULL; + dbs_by_addresses = NULL; if (default_db) gconf_database_free (default_db); @@ -916,6 +916,87 @@ no_databases_in_use (void) gconf_listeners_count (default_db->listeners) == 0; } +void +gconfd_notify_other_listeners (GConfDatabase *modified_db, + GConfSources *modified_sources, + const char *key) +{ + GList *tmp; + + if (!modified_sources) + return; + + tmp = db_list; + while (tmp != NULL) + { + GConfDatabase *db = tmp->data; + + if (db != modified_db) + { + GList *tmp2; + + tmp2 = modified_sources->sources; + while (tmp2) + { + GConfSource *modified_source = tmp2->data; + + if (gconf_sources_is_affected (db->sources, modified_source, key)) + { + GConfValue *value; + GError *error; + gboolean is_default; + gboolean is_writable; + + error = NULL; + value = gconf_database_query_value (db, + key, + NULL, + TRUE, + NULL, + &is_default, + &is_writable, + &error); + if (error != NULL) + { + gconf_log (GCL_WARNING, + _("Error obtaining new value for `%s': %s"), + key, error->message); + g_error_free (error); + return; + } + +#ifdef HAVE_ORBIT + gconf_database_corba_notify_listeners (db, + NULL, + key, + value, + is_default, + is_writable, + FALSE); +#endif +#ifdef HAVE_DBUS + gconf_database_dbus_notify_listeners (db, + NULL, + key, + value, + is_default, + is_writable, + FALSE); +#endif + + if (value) + gconf_value_free (value); + } + + tmp2 = tmp2->next; + } + } + + tmp = tmp->next; + } +} + + /* * Cleanup */ @@ -940,3 +1021,4 @@ gconfd_in_shutdown (void) { return in_shutdown; } + diff --git a/gconf/gconfd.h b/gconf/gconfd.h index 04036c7a..d468ac0b 100644 --- a/gconf/gconfd.h +++ b/gconf/gconfd.h @@ -27,19 +27,19 @@ G_BEGIN_DECLS #include "gconf-error.h" #include "gconf-database.h" - -void gconfd_need_log_cleanup (void); +void gconfd_need_log_cleanup (void); /* This list should not be freed */ -GList * gconfd_get_database_list (void); - -GConfDatabase *gconfd_lookup_database (const gchar *address); -GConfDatabase* gconfd_obtain_database (const gchar *address, - GError **err); - -void gconf_main_quit (void); +GList * gconfd_get_database_list (void); +GConfDatabase *gconfd_lookup_database (GSList *addresses); +GConfDatabase* gconfd_obtain_database (GSList *addresses, + GError **err); +void gconf_main_quit (void); +gboolean gconfd_in_shutdown (void); +void gconfd_notify_other_listeners (GConfDatabase *modified_db, + GConfSources *modified_sources, + const char *key); -gboolean gconfd_in_shutdown (void); G_END_DECLS diff --git a/gconf/gconftool.c b/gconf/gconftool.c index 6a2bf597..7ca98d9e 100644 --- a/gconf/gconftool.c +++ b/gconf/gconftool.c @@ -70,6 +70,7 @@ static int long_docs_mode = FALSE; static int schema_name_mode = FALSE; static int associate_schema_mode = FALSE; static int dissociate_schema_mode = FALSE; +static int ignore_schema_defaults = FALSE; static int default_source_mode = FALSE; static int recursive_unset_mode = FALSE; static int do_version = FALSE; @@ -410,6 +411,15 @@ struct poptOption options[] = { NULL }, { + "ignore-schema-defaults", + '\0', + POPT_ARG_NONE, + &ignore_schema_defaults, + 0, + N_("Ignore schema defaults when reading values."), + NULL + }, + { "get-default-source", '\0', POPT_ARG_NONE, @@ -588,7 +598,7 @@ main (int argc, char** argv) { g_printerr (_("--set_schema should not be used with --get, --set, --unset, --all-entries, --all-dirs\n")); return 1; - } + } if ((value_type != NULL) && !(set_mode || set_schema_mode)) { @@ -602,6 +612,14 @@ main (int argc, char** argv) return 1; } + if (ignore_schema_defaults && !(get_mode || all_entries_mode || + dump_values || recursive_list || + get_list_size_mode || get_list_element_mode)) + { + g_printerr (_("--ignore-schema-defaults is only relevant with --get, --all-entries, --dump, --recursive-list, --get-list-size or --get-list-element\n")); + return 1; + } + if (ping_gconfd && (shutdown_gconfd || set_mode || get_mode || unset_mode || all_subdirs_mode || all_entries_mode || recursive_list || get_type_mode || get_list_size_mode || get_list_element_mode || @@ -703,12 +721,6 @@ main (int argc, char** argv) return 1; } - if (config_source && !use_local_source) - { - g_printerr (_("You should use --direct when using a non-default configuration source\n")); - return 1; - } - if (!gconf_init(argc, argv, &err)) { g_printerr (_("Failed to init GConf: %s\n"), err->message); @@ -780,10 +792,16 @@ main (int argc, char** argv) conf = gconf_engine_get_default(); else { + GSList *addresses; + + addresses = gconf_persistent_name_get_address_list (config_source); + if (use_local_source) - conf = gconf_engine_get_local(config_source, &err); + conf = gconf_engine_get_local_for_addresses (addresses, &err); else - conf = gconf_engine_get_for_address(config_source, &err); + conf = gconf_engine_get_for_addresses (addresses, &err); + + gconf_address_list_free (addresses); } if (conf == NULL) @@ -1226,7 +1244,8 @@ list_pairs_in_dir(GConfEngine* conf, const gchar* dir, guint depth) GConfEntry* pair = tmp->data; gchar* s; - if (gconf_entry_get_value (pair)) + if (gconf_entry_get_value (pair) && + (!ignore_schema_defaults || !gconf_entry_get_is_default (pair))) s = gconf_value_to_string (gconf_entry_get_value (pair)); else s = g_strdup(_("(no value set)")); @@ -1497,7 +1516,8 @@ dump_entries_in_dir(GConfEngine* conf, const gchar* dir, const gchar* base_dir) g_print (" <schema_key>%s</schema_key>\n", get_key_relative(gconf_entry_get_schema_name(entry), base_dir)); - if (entry->value) + if (entry->value && + (!ignore_schema_defaults || !gconf_entry_get_is_default(entry))) print_value_in_xml(entry->value, 6); g_print (" </entry>\n"); @@ -1541,6 +1561,21 @@ do_spawn_daemon(GConfEngine* conf) } } +static inline GConfValue * +get_maybe_without_default (GConfEngine *conf, + const gchar *key, + GError **err) +{ + if (!ignore_schema_defaults) + { + return gconf_engine_get (conf, key, err); + } + else + { + return gconf_engine_get_without_default (conf, key, err); + } +} + static int do_get(GConfEngine* conf, const gchar** args) { @@ -1559,7 +1594,7 @@ do_get(GConfEngine* conf, const gchar** args) err = NULL; - value = gconf_engine_get (conf, *args, &err); + value = get_maybe_without_default (conf, *args, &err); if (value != NULL) { @@ -1818,7 +1853,7 @@ do_get_type(GConfEngine* conf, const gchar** args) err = NULL; - value = gconf_engine_get (conf, *args, &err); + value = get_maybe_without_default (conf, *args, &err); if (value != NULL) { @@ -1856,7 +1891,7 @@ do_get_list_size(GConfEngine* conf, const gchar** args) return 1; } - list = gconf_engine_get (conf, *args, &err); + list = get_maybe_without_default (conf, *args, &err); if (list == NULL) { @@ -1901,7 +1936,7 @@ do_get_list_element(GConfEngine* conf, const gchar** args) return 1; } - list = gconf_engine_get (conf, *args, &err); + list = get_maybe_without_default (conf, *args, &err); if (list == NULL) { @@ -2763,7 +2798,6 @@ set_values(GConfEngine* conf, const gchar* base_dir, const gchar* key, const cha { GSList* tmp; gchar* full_key; - gchar* full_schema_key; if (base_dir) full_key = gconf_concat_dir_and_key(base_dir, key); @@ -2772,23 +2806,17 @@ set_values(GConfEngine* conf, const gchar* base_dir, const gchar* key, const cha if (schema_key) { + gchar* full_schema_key; + if (base_dir && *schema_key != '/') full_schema_key = gconf_concat_dir_and_key(base_dir, schema_key); else full_schema_key = g_strdup(schema_key); - } - else - full_schema_key = NULL; - - tmp = values; - while (tmp) - { - GConfValue* value = tmp->data; - GError* error; if (full_schema_key) { - error = NULL; + GError* error = NULL; + if (!gconf_engine_associate_schema(conf, full_key, full_schema_key, &error)) { g_assert(error != NULL); @@ -2797,7 +2825,16 @@ set_values(GConfEngine* conf, const gchar* base_dir, const gchar* key, const cha full_schema_key, full_key, error->message); g_error_free(error); } - } + + g_free(full_schema_key); + } + } + + tmp = values; + while (tmp) + { + GConfValue* value = tmp->data; + GError* error; error = NULL; gconf_engine_set(conf, full_key, value, &error); @@ -2811,7 +2848,6 @@ set_values(GConfEngine* conf, const gchar* base_dir, const gchar* key, const cha tmp = tmp->next; } - g_free(full_schema_key); g_free(full_key); } @@ -2840,7 +2876,7 @@ process_entry(GConfEngine* conf, xmlNodePtr node, const gchar** base_dirs, const iter = iter->next; } - if (key && values) + if (key && (values || schema_key)) { if (!base_dirs) set_values(conf, orig_base, key, schema_key, values); diff --git a/tests/testbackend.c b/tests/testbackend.c index e56244db..46d42735 100644 --- a/tests/testbackend.c +++ b/tests/testbackend.c @@ -59,8 +59,8 @@ foreach_recursive (GConfSource *source, GError *error; error = NULL; - entries = (* source->backend->vtable->all_entries) (source, dir_key, - locales, &error); + entries = (* source->backend->vtable.all_entries) (source, dir_key, + locales, &error); exit_if_error (error); tmp = entries; @@ -90,8 +90,8 @@ foreach_recursive (GConfSource *source, g_slist_free (entries); error = NULL; - subdirs = (* source->backend->vtable->all_subdirs) (source, dir_key, - &error); + subdirs = (* source->backend->vtable.all_subdirs) (source, dir_key, + &error); exit_if_error (error); tmp = subdirs; @@ -140,7 +140,7 @@ sync_and_clear (GConfSource *source) return; err = NULL; - if (!(* source->backend->vtable->sync_all) (source, &err)) + if (!(* source->backend->vtable.sync_all) (source, &err)) { g_printerr ("Failed to sync: %s\n", err->message); g_error_free (err); @@ -148,7 +148,7 @@ sync_and_clear (GConfSource *source) exit (1); } - (* source->backend->vtable->clear_cache) (source); + (* source->backend->vtable.clear_cache) (source); } static void @@ -283,10 +283,10 @@ check_unset (GConfSource *source) while (*keyp) { - (* source->backend->vtable->unset_value) (source, - *keyp, - NULL, - &err); + (* source->backend->vtable.unset_value) (source, + *keyp, + NULL, + &err); if (err != NULL) { @@ -301,11 +301,11 @@ check_unset (GConfSource *source) sync_and_clear (source); - val = (* source->backend->vtable->query_value) (source, - *keyp, - locales, - NULL, - &err); + val = (* source->backend->vtable.query_value) (source, + *keyp, + locales, + NULL, + &err); if (val) valstr = gconf_value_to_string (val); @@ -330,7 +330,7 @@ set_value (GConfSource *source, GError *tmp_err; tmp_err = NULL; - (* source->backend->vtable->set_value) (source, key, value, &tmp_err); + (* source->backend->vtable.set_value) (source, key, value, &tmp_err); if (tmp_err) g_propagate_error (err, tmp_err); @@ -437,7 +437,7 @@ get_value (GConfSource *source, const char *key, GError **err) { - return (* source->backend->vtable->query_value) (source, key, locales, NULL, err); + return (* source->backend->vtable.query_value) (source, key, locales, NULL, err); } static char* diff --git a/tests/testgconf.c b/tests/testgconf.c index 080e684b..79e09e48 100644 --- a/tests/testgconf.c +++ b/tests/testgconf.c @@ -800,6 +800,9 @@ list_of_floats(void) } +/* FIXME: change the list of floats to bool for now since dbus doesn't work well + * with lists of doubles. + */ static void check_list_storage(GConfEngine* conf) { @@ -808,7 +811,8 @@ check_list_storage(GConfEngine* conf) guint i; GConfValueType list_types[] = { GCONF_VALUE_INT, GCONF_VALUE_INT, GCONF_VALUE_STRING, GCONF_VALUE_STRING, - GCONF_VALUE_FLOAT, GCONF_VALUE_FLOAT, + /*GCONF_VALUE_FLOAT, GCONF_VALUE_FLOAT,*/ + GCONF_VALUE_BOOL, GCONF_VALUE_BOOL, GCONF_VALUE_BOOL, GCONF_VALUE_BOOL }; GSList* lists[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; const guint n_lists = sizeof(lists)/sizeof(lists[0]); @@ -824,7 +828,7 @@ check_list_storage(GConfEngine* conf) lists[3] = NULL; /* of float */ - lists[4] = list_of_floats(); + lists[4] = list_of_bools(); /*list_of_floats();*/ lists[5] = NULL; /* of bool */ diff --git a/tests/testpersistence.c b/tests/testpersistence.c index f2753ab6..eb236da3 100644 --- a/tests/testpersistence.c +++ b/tests/testpersistence.c @@ -798,6 +798,9 @@ list_of_floats(void) } +/* FIXME: change the list of floats to bool for now since dbus doesn't work well + * with lists of doubles. + */ static void check_list_storage(GConfEngine* conf) { @@ -806,7 +809,8 @@ check_list_storage(GConfEngine* conf) guint i; GConfValueType list_types[] = { GCONF_VALUE_INT, GCONF_VALUE_INT, GCONF_VALUE_STRING, GCONF_VALUE_STRING, - GCONF_VALUE_FLOAT, GCONF_VALUE_FLOAT, + /*GCONF_VALUE_FLOAT, GCONF_VALUE_FLOAT,*/ + GCONF_VALUE_BOOL, GCONF_VALUE_BOOL, GCONF_VALUE_BOOL, GCONF_VALUE_BOOL }; GSList* lists[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; const guint n_lists = sizeof(lists)/sizeof(lists[0]); @@ -822,7 +826,7 @@ check_list_storage(GConfEngine* conf) lists[3] = NULL; /* of float */ - lists[4] = list_of_floats(); + lists[4] = list_of_bools(); /*list_of_floats();*/ lists[5] = NULL; /* of bool */ |