summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Tarricone <brian@tarricone.org>2007-09-06 09:27:05 +0000
committerBrian Tarricone <brian@tarricone.org>2007-09-06 09:27:05 +0000
commit63affd4acd1d4aca358999235d83303c76826d2f (patch)
tree88a3b5377d68a20120a9669bff354cafdfe04522
parentf1b43fa69c1b83fd89f60bbeb6f1dc7819120545 (diff)
downloadxfconf-63affd4acd1d4aca358999235d83303c76826d2f.tar.gz
implement most of the perchannel-xml backend. reading stuff from
the xml files isn't implemented yet, but writing values is done and appears to work (Old svn revision: 26728)
-rw-r--r--xfconfd/Makefile.am27
-rw-r--r--xfconfd/xfconf-backend-perchannel-xml.c470
-rw-r--r--xfconfd/xfconf-backend.c85
-rw-r--r--xfconfd/xfconf-backend.h30
-rw-r--r--xfconfd/xfconf-daemon.c10
5 files changed, 586 insertions, 36 deletions
diff --git a/xfconfd/Makefile.am b/xfconfd/Makefile.am
index bfd012e..80a55bb 100644
--- a/xfconfd/Makefile.am
+++ b/xfconfd/Makefile.am
@@ -44,18 +44,27 @@ service_DATA = $(service_in_files:.service.in=.service)
%.service: %.service.in
sed -e "s,\@bindir\@,$(bindir),g" < $< > $@
-if MAINTAINER_MODE
-
-xfconf-dbus-server.h: $(top_srcdir)/common/xfconf-dbus.xml
- dbus-binding-tool --mode=glib-server --prefix=xfconf $< > $@
-
-endif
-
+DISTCLEANFILES = \
+ $(service_DATA)
EXTRA_DIST = \
xfconf-backend-perchannel-xml.c \
xfconf-backend-perchannel-xml.h \
$(service_in_files)
-DISTCLEANFILES = \
- $(service_DATA)
+
+if MAINTAINER_MODE
+
+xfconf_built_sources = \
+ xfconf-dbus-server.h
+
+DISTCLEANFILES += \
+ $(xfconf_built_sources)
+
+BUILT_SOURCES = \
+ $(xfconf_built_sources)
+
+xfconf-dbus-server.h: $(top_srcdir)/common/xfconf-dbus.xml
+ dbus-binding-tool --mode=glib-server --prefix=xfconf $< > $@
+
+endif
diff --git a/xfconfd/xfconf-backend-perchannel-xml.c b/xfconfd/xfconf-backend-perchannel-xml.c
index 6f0a0ec..1eb80cf 100644
--- a/xfconfd/xfconf-backend-perchannel-xml.c
+++ b/xfconfd/xfconf-backend-perchannel-xml.c
@@ -21,16 +21,38 @@
#include <config.h>
#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
#include <libxfce4util/libxfce4util.h>
+#include <dbus/dbus-glib.h>
#include "xfconf-backend-perchannel-xml.h"
#include "xfconf-backend.h"
+#include "xfconf-util.h"
+
+#define CACHE_TIMEOUT (20*60*1000) /* 20 minutes */
+#define WRITE_TIMEOUT (5*1000) /* 5 secionds */
struct _XfconfBackendPerchannelXml
{
GObject parent;
gchar *config_path;
+
+ GTree *channels;
+
+ guint save_id;
+ GList *dirty_channels;
};
typedef struct _XfconfBackendPerchannelXmlClass
@@ -76,6 +98,18 @@ static gboolean xfconf_backend_perchannel_xml_remove_channel(XfconfBackend *back
static gboolean xfconf_backend_perchannel_xml_flush(XfconfBackend *backend,
GError **error);
+static void xfconf_backend_perchannel_xml_schedule_save(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel);
+
+static GTree *xfconf_backend_perchannel_xml_create_channel(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel);
+static GTree *xfconf_backend_perchannel_xml_load_channel(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel,
+ GError **error);
+static gboolean xfconf_backend_perchannel_xml_flush_channel(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel,
+ GError **error);
+
G_DEFINE_TYPE_WITH_CODE(XfconfBackendPerchannelXml, xfconf_backend_perchannel_xml, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE(XFCONF_TYPE_BACKEND,
@@ -93,12 +127,28 @@ xfconf_backend_perchannel_xml_class_init(XfconfBackendPerchannelXmlClass *klass)
static void
xfconf_backend_perchannel_xml_init(XfconfBackendPerchannelXml *instance)
{
-
+ instance->channels = g_tree_new_full((GCompareDataFunc)g_ascii_strcasecmp,
+ NULL,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)g_tree_destroy);
}
static void
xfconf_backend_perchannel_xml_finalize(GObject *obj)
{
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(obj);
+
+ if(xbpx->save_id) {
+ g_source_remove(xbpx->save_id);
+ xbpx->save_id = 0;
+ }
+
+ if(xbpx->dirty_channels)
+ xfconf_backend_perchannel_xml_flush(XFCONF_BACKEND(xbpx), NULL);
+
+ g_tree_destroy(xbpx->channels);
+ g_free(xbpx->config_path);
+
G_OBJECT_CLASS(xfconf_backend_perchannel_xml_parent_class)->finalize(obj);
}
@@ -126,7 +176,8 @@ xfconf_backend_perchannel_xml_initialize(XfconfBackend *backend,
if(!path || !g_file_test(path, G_FILE_TEST_IS_DIR)) {
if(error) {
- g_set_error(error, G_FILE_ERROR, 0,
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_WRITE_FAILURE,
_("Unable to create configuration directory"));
}
g_free(path);
@@ -145,7 +196,31 @@ xfconf_backend_perchannel_xml_set(XfconfBackend *backend,
const GValue *value,
GError **error)
{
- return FALSE;
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ GTree *properties = g_tree_lookup(xbpx->channels, channel);
+ GValue *cur_val;
+
+ if(!properties) {
+ properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel,
+ NULL);
+ if(!properties) {
+ properties = xfconf_backend_perchannel_xml_create_channel(xbpx,
+ channel);
+ }
+ }
+
+ cur_val = g_tree_lookup(properties, property);
+ if(cur_val)
+ g_value_unset(cur_val);
+ else {
+ cur_val = g_new0(GValue, 1);
+ g_tree_insert(properties, g_strdup(property), cur_val);
+ }
+
+ g_value_copy(value, g_value_init(cur_val, G_VALUE_TYPE(value)));
+ xfconf_backend_perchannel_xml_schedule_save(xbpx, channel);
+
+ return TRUE;
}
static gboolean
@@ -155,6 +230,43 @@ xfconf_backend_perchannel_xml_get(XfconfBackend *backend,
GValue *value,
GError **error)
{
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ GTree *properties = g_tree_lookup(xbpx->channels, channel);
+ GValue *cur_val;
+
+ if(!properties) {
+ properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel,
+ error);
+ if(!properties)
+ return FALSE;
+ }
+
+ cur_val = g_tree_lookup(properties, property);
+ if(!cur_val) {
+ if(error) {
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND,
+ _("Property \"%s\" does not exist on channel \"%s\""),
+ property, channel);
+ }
+ return FALSE;
+ }
+
+ g_value_copy(cur_val, g_value_init(value, G_VALUE_TYPE(cur_val)));
+
+ return TRUE;
+}
+
+static gboolean
+tree_to_hash_table(gpointer key,
+ gpointer value,
+ gpointer data)
+{
+ GValue *value1 = g_new0(GValue, 1);
+
+ g_value_copy(value, g_value_init(value1, G_VALUE_TYPE(value)));
+ g_hash_table_insert((GHashTable *)data, g_strdup(key), value1);
+
return FALSE;
}
@@ -164,7 +276,19 @@ xfconf_backend_perchannel_xml_get_all(XfconfBackend *backend,
GHashTable *properties,
GError **error)
{
- return FALSE;
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ GTree *properties1 = g_tree_lookup(xbpx->channels, channel);
+
+ if(!properties1) {
+ properties1 = xfconf_backend_perchannel_xml_load_channel(xbpx, channel,
+ error);
+ if(!properties1)
+ return FALSE;
+ }
+
+ g_tree_foreach(properties1, tree_to_hash_table, properties);
+
+ return TRUE;
}
static gboolean
@@ -174,7 +298,24 @@ xfconf_backend_perchannel_xml_exists(XfconfBackend *backend,
gboolean *exists,
GError **error)
{
- return FALSE;
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ GTree *properties = g_tree_lookup(xbpx->channels, channel);
+
+ if(!properties) {
+ properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel,
+ NULL);
+ if(!properties) {
+ *exists = FALSE;
+ return TRUE;
+ }
+ }
+
+ if(g_tree_lookup(properties, property))
+ *exists = TRUE;
+ else
+ *exists = FALSE;
+
+ return TRUE;
}
static gboolean
@@ -183,7 +324,30 @@ xfconf_backend_perchannel_xml_remove(XfconfBackend *backend,
const gchar *property,
GError **error)
{
- return FALSE;
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ GTree *properties = g_tree_lookup(xbpx->channels, channel);
+
+ if(!properties) {
+ properties = xfconf_backend_perchannel_xml_load_channel(xbpx, channel,
+ error);
+ if(!properties)
+ return FALSE;
+ }
+
+ if(!g_tree_lookup(properties, property)) {
+ if(error) {
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND,
+ _("Property \"%s\" does not exist on channel \"%s\""),
+ property, channel);
+ }
+ return FALSE;
+ }
+
+ g_tree_remove(properties, property);
+ xfconf_backend_perchannel_xml_schedule_save(xbpx, channel);
+
+ return TRUE;
}
static gboolean
@@ -191,12 +355,304 @@ xfconf_backend_perchannel_xml_remove_channel(XfconfBackend *backend,
const gchar *channel,
GError **error)
{
- return FALSE;
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ gchar *filename;
+ GList *dirty;
+
+ if((dirty = g_list_find_custom(xbpx->dirty_channels, channel,
+ (GCompareFunc)g_ascii_strcasecmp)))
+ {
+ xbpx->dirty_channels = g_list_remove(xbpx->dirty_channels, dirty);
+ if(!xbpx->dirty_channels && xbpx->save_id) {
+ g_source_remove(xbpx->save_id);
+ xbpx->save_id = 0;
+ }
+ }
+
+ g_tree_remove(xbpx->channels, channel);
+
+ filename = g_strdup_printf("%s/%s.xml", xbpx->config_path, channel);
+ if(unlink(filename)) {
+ if(error) {
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_WRITE_FAILURE,
+ _("Unable to remove channel \"%s\": %s"),
+ channel, strerror(errno));
+ }
+ g_free(filename);
+ return FALSE;
+ }
+ g_free(filename);
+
+ return TRUE;
}
static gboolean
xfconf_backend_perchannel_xml_flush(XfconfBackend *backend,
GError **error)
{
+ XfconfBackendPerchannelXml *xbpx = XFCONF_BACKEND_PERCHANNEL_XML(backend);
+ GList *l;
+
+ for(l = xbpx->dirty_channels; l; l = l->next)
+ xfconf_backend_perchannel_xml_flush_channel(xbpx, l->data, error);
+
return TRUE;
}
+
+
+
+static gboolean
+xfconf_backend_perchannel_xml_save_timeout(gpointer data)
+{
+ XFCONF_BACKEND_PERCHANNEL_XML(data)->save_id = 0;
+ xfconf_backend_perchannel_xml_flush(XFCONF_BACKEND(data), NULL);
+
+ return FALSE;
+}
+
+static void
+xfconf_backend_perchannel_xml_schedule_save(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel)
+{
+ if(!g_list_find_custom(xbpx->dirty_channels, channel,
+ (GCompareFunc)g_ascii_strcasecmp))
+ {
+ gpointer orig_key = NULL, val = NULL;
+
+ if(!g_tree_lookup_extended(xbpx->channels, channel, &orig_key, &val)) {
+ g_warning("Attempt to schedule save for a nonexistent channel.");
+ return;
+ }
+
+ xbpx->dirty_channels = g_list_prepend(xbpx->dirty_channels, orig_key);
+ }
+
+ if(xbpx->save_id)
+ g_source_remove(xbpx->save_id);
+
+ xbpx->save_id = g_timeout_add(WRITE_TIMEOUT,
+ xfconf_backend_perchannel_xml_save_timeout,
+ xbpx);
+}
+
+static GTree *
+xfconf_backend_perchannel_xml_create_channel(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel)
+{
+ GTree *properties;
+
+ if((properties = g_tree_lookup(xbpx->channels, channel))) {
+ g_warning("Attempt to create channel when one already exists.");
+ return properties;
+ }
+
+ properties = g_tree_new_full((GCompareDataFunc)strcmp, NULL,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)xfconf_g_value_free);
+ g_tree_insert(xbpx->channels, g_strdup(channel), properties);
+
+ return properties;
+}
+
+static GTree *
+xfconf_backend_perchannel_xml_load_channel(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel,
+ GError **error)
+{
+ GTree *properties = NULL;
+ gchar *filename;
+
+ filename = g_strdup_printf("%s/%s.xml", xbpx->config_path, channel);
+ if(!g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
+ if(error) {
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND,
+ _("Channel \"%s\" does not exist"), channel);
+ }
+ g_free(filename);
+ return NULL;
+ }
+
+//out:
+ g_free(filename);
+
+ return properties;
+}
+
+typedef struct
+{
+ FILE *fp;
+ gboolean error_occurred;
+} NodeWriterData;
+
+static gboolean
+tree_write_nodes(gpointer key,
+ gpointer value_p,
+ gpointer data)
+{
+ NodeWriterData *ndata = data;
+ const gchar *property = key, *type_str = NULL;
+ const GValue *value = value_p;
+ gchar *value_str = NULL;
+
+ /*
+ * I know the suggested config value scheme implies some kind of hierarchical
+ * list of properties, but I'm lazy, so we're just going to store them flat.
+ */
+
+ switch(G_VALUE_TYPE(value)) {
+ case G_TYPE_STRING:
+ value_str = g_markup_escape_text(g_value_get_string(value), -1);
+ type_str = "string";
+ break;
+
+ case G_TYPE_INT:
+ value_str = g_strdup_printf("%d", g_value_get_int(value));
+ type_str = "int";
+ break;
+
+ case G_TYPE_INT64:
+ value_str = g_strdup_printf("%" G_GINT64_FORMAT,
+ g_value_get_int64(value));
+ type_str = "int64";
+ break;
+
+ case G_TYPE_DOUBLE:
+ value_str = g_strdup_printf("%f", g_value_get_double(value));
+ type_str = "double";
+ break;
+
+ case G_TYPE_BOOLEAN:
+ value_str = g_strdup(g_value_get_boolean(value) ? "true" : "false");
+ type_str = "bool";
+ break;
+
+ default:
+ if(G_VALUE_TYPE(value) == dbus_g_type_get_collection("GPtrArray",
+ G_TYPE_STRING))
+ {
+ type_str = "strlist";
+ } else {
+ g_warning("Unknown value type %d (\"%s\"), skipping",
+ (int)G_VALUE_TYPE(value), G_VALUE_TYPE_NAME(value));
+ ndata->error_occurred = TRUE;
+ return TRUE;
+ }
+ break;
+ }
+
+ if(fprintf(ndata->fp, " <property name=\"%s\" type=\"%s\"",
+ property, type_str) < 0)
+ {
+ ndata->error_occurred = TRUE;
+ goto out;
+ }
+
+ if(value_str) {
+ if(fprintf(ndata->fp, " value=\"%s\"/>\n", value_str) < 0) {
+ ndata->error_occurred = TRUE;
+ goto out;
+ }
+ } else {
+ GPtrArray *arr;
+ gint i;
+
+ if(fputs(">\n", ndata->fp) == EOF) {
+ ndata->error_occurred = TRUE;
+ goto out;
+ }
+
+ arr = g_value_get_boxed(value);
+ for(i = 0; i < arr->len; ++i) {
+ value_str = g_markup_escape_text(arr->pdata[i], -1);
+ if(fprintf(ndata->fp, " <string>%s</string\n", value_str) < 0) {
+ ndata->error_occurred = TRUE;
+ goto out;
+ }
+ g_free(value_str);
+ }
+ value_str = NULL;
+
+ if(fputs(" </property>\n", ndata->fp) == EOF) {
+ ndata->error_occurred = TRUE;
+ goto out;
+ }
+ }
+
+out:
+ g_free(value_str);
+
+ return ndata->error_occurred;
+}
+
+
+static gboolean
+xfconf_backend_perchannel_xml_flush_channel(XfconfBackendPerchannelXml *xbpx,
+ const gchar *channel,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ GTree *properties = g_tree_lookup(xbpx->channels, channel);
+ gchar *filename = NULL, *filename_tmp = NULL;
+ FILE *fp = NULL;
+ NodeWriterData ndata;
+
+ if(!properties) {
+ if(error) {
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND,
+ _("Channel \"%s\" does not exist"), channel);
+ }
+ return FALSE;
+ }
+
+ filename = g_strdup_printf("%s/%s.xml", xbpx->config_path, channel);
+ filename_tmp = g_strconcat(filename, ".new", NULL);
+
+ fp = fopen(filename_tmp, "w");
+ if(!fp)
+ goto out;
+
+ if(fputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n", fp) == EOF
+ || fprintf(fp, "<channel name=\"%s\" version=\"1\">\n", channel) < 0)
+ {
+ goto out;
+ }
+
+ ndata.fp = fp;
+ ndata.error_occurred = FALSE;
+ g_tree_foreach(properties, tree_write_nodes, &ndata);
+ if(ndata.error_occurred)
+ goto out;
+
+ if(fputs("</channel>\n", fp) == EOF)
+ goto out;
+
+ if(fclose(fp)) {
+ fp = NULL;
+ goto out;
+ }
+ fp = NULL;
+
+ if(rename(filename_tmp, filename))
+ goto out;
+
+ ret = TRUE;
+
+out:
+ if(!ret && error && !*error) {
+ g_set_error(error, XFCONF_BACKEND_ERROR,
+ XFCONF_BACKEND_ERROR_WRITE_FAILURE,
+ _("Unable to write channel \"%s\": %s"),
+ channel, strerror(errno));
+ }
+
+ if(fp)
+ fclose(fp);
+
+ g_free(filename);
+ g_free(filename_tmp);
+
+ return ret;
+}
diff --git a/xfconfd/xfconf-backend.c b/xfconfd/xfconf-backend.c
index 7778c07..96153d2 100644
--- a/xfconfd/xfconf-backend.c
+++ b/xfconfd/xfconf-backend.c
@@ -21,10 +21,14 @@
#include <config.h>
#endif
+#include <dbus/dbus-glib.h>
+
#include "xfconf-backend.h"
static GQuark error_quark = 0;
+static void xfconf_backend_base_init(gpointer g_class);
+
/**
* XfconfBackendInterface:
@@ -58,6 +62,32 @@ xfconf_backend_get_error_quark()
return error_quark;
}
+/* unfortunately glib-mkenums can't generate types that are compatible with
+ * dbus error names -- the 'nick' value is used, which can have dashes in it,
+ * which dbus doesn't like. */
+GType
+xfconf_backend_error_get_type()
+{
+ static GType type = 0;
+
+ if(!type) {
+ static const GEnumValue values[] = {
+ { XFCONF_BACKEND_ERROR_UNKNOWN, "XFCONF_BACKEND_ERROR_UNKNOWN", "Unknown" },
+ { XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND, "XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND", "ChannelNotFound" },
+ { XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND, "XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND", "PropertyNotFound" },
+ { XFCONF_BACKEND_ERROR_READ_FAILURE, "XFCONF_BACKEND_ERROR_READ_FAILURE", "ReadFailure" },
+ { XFCONF_BACKEND_ERROR_WRITE_FAILURE, "XFCONF_BACKEND_ERROR_WRITE_FAILURE", "WriteFailure" },
+ { XFCONF_BACKEND_ERROR_INTERNAL_ERROR, "XFCONF_BACKEND_ERROR_INTERNAL_ERROR", "InternalError" },
+ { 0, NULL, NULL }
+ };
+
+ type = g_enum_register_static("XfconfBackendError", values);
+ }
+
+ return type;
+}
+
+
GType
xfconf_backend_get_type()
{
@@ -66,7 +96,7 @@ xfconf_backend_get_type()
if(!backend_type) {
static const GTypeInfo backend_info = {
sizeof(XfconfBackendInterface),
- NULL,
+ xfconf_backend_base_init,
NULL,
NULL,
NULL,
@@ -86,6 +116,22 @@ xfconf_backend_get_type()
+static void
+xfconf_backend_base_init(gpointer g_class)
+{
+ static gboolean _inited = FALSE;
+
+ if(!_inited) {
+ dbus_g_error_domain_register(XFCONF_BACKEND_ERROR,
+ "org.xfce.Xfconf.BackendError",
+ XFCONF_TYPE_BACKEND_ERROR);
+
+ _inited = TRUE;
+ }
+}
+
+
+
/**
* xfconf_backend_initialize:
* @backend: The #XfconfBackend.
@@ -103,7 +149,8 @@ xfconf_backend_initialize(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->initialize, FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->initialize
+ && (!error || !*error), FALSE);
return iface->initialize(backend, error);
}
@@ -131,8 +178,9 @@ xfconf_backend_set(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->set && channel && property && value
- && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->set && channel && *channel
+ && property && *property
+ && value && (!error || !*error), FALSE);
return iface->set(backend, channel, property, value, error);
}
@@ -160,8 +208,9 @@ xfconf_backend_get(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->get && channel && property && value
- && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->get && channel && *channel
+ && property && *property
+ && value && (!error || !*error), FALSE);
return iface->get(backend, channel, property, value, error);
}
@@ -189,8 +238,9 @@ xfconf_backend_get_all(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->get_all && channel && properties
- && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->get_all && channel
+ && *channel && properties
+ && (!error || !*error), FALSE);
return iface->get_all(backend, channel, properties, error);
}
@@ -219,8 +269,10 @@ xfconf_backend_exists(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->exists && channel && property && exists
- && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->exists && channel
+ && *channel && property && *property
+ && exists
+ && (!error || !*error), FALSE);
return iface->exists(backend, channel, property, exists, error);
}
@@ -246,8 +298,9 @@ xfconf_backend_remove(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->remove && channel && property
- && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->remove && channel
+ && *channel && property && *property
+ && (!error || !*error), FALSE);
return iface->remove(backend, channel, property, error);
}
@@ -271,8 +324,9 @@ xfconf_backend_remove_channel(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->remove_channel && channel
- && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->remove_channel && channel
+ && *channel
+ && (!error || !*error), FALSE);
return iface->remove_channel(backend, channel, error);
}
@@ -295,7 +349,8 @@ xfconf_backend_flush(XfconfBackend *backend,
{
XfconfBackendInterface *iface = XFCONF_BACKEND_GET_INTERFACE(backend);
- g_return_val_if_fail(iface && iface->flush && (!error || *error), FALSE);
+ xfconf_backend_return_val_if_fail(iface && iface->flush
+ && (!error || !*error), FALSE);
return iface->flush(backend, error);
}
diff --git a/xfconfd/xfconf-backend.h b/xfconfd/xfconf-backend.h
index b53017b..03d7816 100644
--- a/xfconfd/xfconf-backend.h
+++ b/xfconfd/xfconf-backend.h
@@ -22,15 +22,44 @@
#include <glib-object.h>
+#if defined(GETTEXT_PACKAGE)
+#include <glib/gi18n-lib.h>
+#else
+#include <glib/gi18n.h>
+#endif
+
#define XFCONF_TYPE_BACKEND (xfconf_backend_get_type())
#define XFCONF_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XFCONF_TYPE_BACKEND, XfconfBackend))
#define XFCONF_IS_BACKEND(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XFCONF_TYPE_BACKEND))
#define XFCONF_BACKEND_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE((obj), XFCONF_TYPE_BACKEND, XfconfBackendInterface))
+#define XFCONF_TYPE_BACKEND_ERROR (xfconf_backend_error_get_type())
#define XFCONF_BACKEND_ERROR (xfconf_backend_get_error_quark())
+#define xfconf_backend_return_val_if_fail(cond, val) G_STMT_START{ \
+ if(!(cond)) { \
+ if(error) { \
+ g_set_error(error, XFCONF_BACKEND_ERROR, \
+ XFCONF_BACKEND_ERROR_INTERNAL_ERROR, \
+ _("An internal error occurred; this is probably a bug")); \
+ } \
+ g_return_val_if_fail((cond), (val)); \
+ return (val); /* ensure return even if G_DISABLE_CHECKS */ \
+ } \
+}G_STMT_END
+
G_BEGIN_DECLS
+typedef enum
+{
+ XFCONF_BACKEND_ERROR_UNKNOWN = 0,
+ XFCONF_BACKEND_ERROR_CHANNEL_NOT_FOUND,
+ XFCONF_BACKEND_ERROR_PROPERTY_NOT_FOUND,
+ XFCONF_BACKEND_ERROR_READ_FAILURE,
+ XFCONF_BACKEND_ERROR_WRITE_FAILURE,
+ XFCONF_BACKEND_ERROR_INTERNAL_ERROR,
+} XfconfBackendError;
+
typedef struct _XfconfBackend XfconfBackend;
typedef struct _XfconfBackendInterface XfconfBackendInterface;
@@ -83,6 +112,7 @@ struct _XfconfBackendInterface
void (*_xb_reserved3)();
};
+GType xfconf_backend_error_get_type() G_GNUC_CONST;
GQuark xfconf_backend_get_error_quark();
GType xfconf_backend_get_type() G_GNUC_CONST;
diff --git a/xfconfd/xfconf-daemon.c b/xfconfd/xfconf-daemon.c
index 3a42e62..c3c8059 100644
--- a/xfconfd/xfconf-daemon.c
+++ b/xfconfd/xfconf-daemon.c
@@ -28,7 +28,7 @@
#include "xfconf-backend-factory.h"
#include "xfconf-backend.h"
#include "xfconf-marshal.h"
-
+#include "xfconf-util.h"
static gboolean xfconf_set_property(XfconfDaemon *xfconfd,
const gchar *channel,
@@ -96,9 +96,9 @@ xfconf_daemon_class_init(XfconfDaemonClass *klass)
object_class->finalize = xfconf_daemon_finalize;
- g_signal_new("changed", XFCONF_TYPE_DAEMON, G_SIGNAL_RUN_LAST, 0, NULL,
- NULL, xfconf_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2,
- G_TYPE_STRING, G_TYPE_STRING);
+ g_signal_new("property-changed", XFCONF_TYPE_DAEMON, G_SIGNAL_RUN_LAST, 0,
+ NULL, NULL, xfconf_marshal_VOID__STRING_STRING, G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
dbus_g_object_type_install_info(G_TYPE_FROM_CLASS(klass),
&dbus_glib_xfconf_object_info);
@@ -162,7 +162,7 @@ xfconf_get_all_properties(XfconfDaemon *xfconfd,
*properties = g_hash_table_new_full(g_str_hash, g_str_equal,
(GDestroyNotify)g_free,
- (GDestroyNotify)g_value_unset);
+ (GDestroyNotify)xfconf_g_value_free);
ret = xfconf_backend_get_all(xfconfd->backend, channel, *properties, error);
if(!ret) {