summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hult <rhult@src.gnome.org>2004-04-19 14:42:31 +0000
committerRichard Hult <rhult@src.gnome.org>2004-04-19 14:42:31 +0000
commit687ae98ebb66a485a8b856769fdd94269d707c08 (patch)
treee38cc45e326d13bbe7b525a5c905fc408374a290
parente78a2665d9ce246aaacd4024bcdc7f370915a4c3 (diff)
downloadgconf-dbus.tar.gz
-rw-r--r--ChangeLog322
-rw-r--r--backends/dir-utils.c220
-rw-r--r--backends/dir-utils.h34
-rw-r--r--backends/markup-backend.c42
-rw-r--r--backends/val-encode.c444
-rw-r--r--backends/val-encode.h39
-rw-r--r--backends/xml-backend.c42
-rw-r--r--configure.in36
-rw-r--r--doc/gconf/tmpl/gconf-backend.sgml4
-rw-r--r--doc/gconf/tmpl/gconf-engine.sgml9
-rw-r--r--doc/gconf/tmpl/gconf-internals.sgml10
-rw-r--r--doc/gconf/tmpl/gconf-sources.sgml2
-rw-r--r--doc/gconf/tmpl/gconf-unused.sgml9
-rw-r--r--examples/basic-gconf-app.c6
-rw-r--r--gconf-2.m4.in2
-rw-r--r--gconf.m4.in2
-rw-r--r--gconf/GConfX.idl5
-rw-r--r--gconf/default.path.in10
-rw-r--r--gconf/gconf-backend.c129
-rw-r--r--gconf/gconf-backend.h19
-rw-r--r--gconf/gconf-corba-utils.c69
-rw-r--r--gconf/gconf-corba.c192
-rw-r--r--gconf/gconf-database-corba.c34
-rw-r--r--gconf/gconf-database-corba.h5
-rw-r--r--gconf/gconf-database-dbus.c147
-rw-r--r--gconf/gconf-database-dbus.h23
-rw-r--r--gconf/gconf-database.c226
-rw-r--r--gconf/gconf-dbus-utils.c6
-rw-r--r--gconf/gconf-dbus-utils.h113
-rw-r--r--gconf/gconf-dbus.c182
-rw-r--r--gconf/gconf-engine.h7
-rw-r--r--gconf/gconf-internals.c78
-rw-r--r--gconf/gconf-internals.h6
-rw-r--r--gconf/gconf-sources.c299
-rw-r--r--gconf/gconf-sources.h33
-rw-r--r--gconf/gconf.h2
-rw-r--r--gconf/gconfd-corba.c94
-rw-r--r--gconf/gconfd-corba.h2
-rw-r--r--gconf/gconfd-dbus.c61
-rw-r--r--gconf/gconfd.c160
-rw-r--r--gconf/gconfd.h20
-rw-r--r--gconf/gconftool.c94
-rw-r--r--tests/testbackend.c34
-rw-r--r--tests/testgconf.c8
-rw-r--r--tests/testpersistence.c8
45 files changed, 1985 insertions, 1304 deletions
diff --git a/ChangeLog b/ChangeLog
index 37a36397..be5c66d5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 */