summaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorHavoc Pennington <hp@src.gnome.org>1999-12-23 22:06:30 +0000
committerHavoc Pennington <hp@src.gnome.org>1999-12-23 22:06:30 +0000
commit38eb7950e7653b4704d465bf56fbd76cd00ac23b (patch)
tree949dc6d2cd365aa613c897c39bbc38377d2b30f4 /backends
parent811b3f1a8aba1902d3c0ca0ed041e4033c9a91e6 (diff)
downloadgconf-38eb7950e7653b4704d465bf56fbd76cd00ac23b.tar.gz
work on the XML backend cleanup
Diffstat (limited to 'backends')
-rw-r--r--backends/Makefile.am6
-rw-r--r--backends/xml-cache.c488
-rw-r--r--backends/xml-cache.h43
-rw-r--r--backends/xml-dir.c219
-rw-r--r--backends/xml-dir.h87
-rw-r--r--backends/xml-entry.c64
6 files changed, 821 insertions, 86 deletions
diff --git a/backends/Makefile.am b/backends/Makefile.am
index dd604582..f2d06618 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -5,6 +5,12 @@ backenddir = $(libdir)/gconf
backend_LTLIBRARIES = libgconfbackend-xml.la
libgconfbackend_xml_la_SOURCES = \
+ xml-cache.h \
+ xml-cache.c \
+ xml-dir.h \
+ xml-dir.c \
+ xml-entry.h \
+ xml-entry.c \
xml-backend.c
libgconfbackend_xml_la_LDFLAGS = -avoid-version -module
diff --git a/backends/xml-cache.c b/backends/xml-cache.c
new file mode 100644
index 00000000..6ddfabe8
--- /dev/null
+++ b/backends/xml-cache.c
@@ -0,0 +1,488 @@
+/* GConf
+ * Copyright (C) 1999 Red Hat Inc.
+ *
+ * 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 "xml-cache.h"
+#include <gconf/gconf-internals.h>
+
+#include <time.h>
+
+/* Quick hack so I can mark strings */
+
+#ifdef _
+#warning "_ already defined"
+#else
+#define _(x) x
+#endif
+
+#ifdef N_
+#warning "N_ already defined"
+#else
+#define N_(x) x
+#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);
+ }
+}
+#endif
+
+static gboolean
+cache_is_nonexistent(Cache* cache,
+ const gchar* key);
+
+static void
+cache_set_nonexistent (Cache* cache,
+ const gchar* key,
+ gboolean setting);
+
+static void
+cache_insert (Cache* cache,
+ Dir* d);
+
+struct _Cache {
+ gchar* root_dir;
+ GHashTable* cache;
+ GHashTable* nonexistent_cache;
+ GSList* deleted;
+ /*
+ List of lists of dirs marked deleted, in the
+ proper order; should be synced by deleting each
+ list from front to end, starting with the first
+ list.
+ */
+
+};
+
+Cache*
+cache_new (const gchar *root_dir)
+{
+ Cache* cache;
+
+ cache = g_new(Cache, 1);
+
+ cache->root_dir = g_strdup(root_dir);
+
+ cache->cache = g_hash_table_new(g_str_hash, g_str_equal);
+ cache->nonexistent_cache = g_hash_table_new(g_str_hash, g_str_equal);
+
+ cache->deleted = NULL;
+
+ return cache;
+}
+
+static void cache_destroy_foreach(const gchar* key,
+ Dir* dir, gpointer data);
+
+static void cache_destroy_nonexistent_foreach(gchar* key,
+ gpointer val,
+ gpointer data);
+
+void
+cache_destroy (Cache *cache)
+{
+ GSList *iter;
+
+ g_free(cache->root_dir);
+ g_hash_table_foreach(cache->cache, (GHFunc)cache_destroy_foreach,
+ NULL);
+ g_hash_table_foreach(cache->nonexistent_cache,
+ (GHFunc)cache_destroy_nonexistent_foreach,
+ NULL);
+ g_hash_table_destroy(cache->cache);
+ g_hash_table_destroy(cache->nonexistent_cache);
+
+ if (cache->deleted != NULL)
+ gconf_log(GCL_WARNING, _("Unsynced directory deletions when shutting down XML backend"));
+
+ iter = cache->deleted;
+
+ while (iter != NULL)
+ {
+ g_slist_free(iter->data);
+
+ iter = g_slist_next(iter);
+ }
+ g_slist_free(cache->deleted);
+
+ g_free(cache);
+}
+
+
+typedef struct _SyncData SyncData;
+struct _SyncData {
+ gboolean failed;
+ Cache* dc;
+};
+
+static void
+cache_sync_foreach(const gchar* key,
+ Dir* dir,
+ SyncData* sd)
+{
+ GConfError* error = NULL;
+
+ /* log errors but don't report the specific ones */
+ if (!dir_sync(dir, &error))
+ {
+ sd->failed = TRUE;
+ g_return_if_fail(error != NULL);
+ gconf_log(GCL_ERR, error->str);
+ gconf_error_destroy(error);
+ }
+ else
+ {
+ g_return_if_fail(error == NULL);
+ }
+}
+
+gboolean
+cache_sync (Cache *cache,
+ GConfError **err)
+{
+ SyncData sd = { FALSE, cache };
+ GSList* delete_list;
+
+ /* First delete pending directories */
+ delete_list = cache->deleted;
+
+ while (delete_list != NULL)
+ {
+ GSList* tmp;
+
+ tmp = delete_list->data;
+
+ while (tmp != NULL)
+ {
+ Dir* d = tmp->data;
+
+ if (!dir_sync(d, NULL)) /* don't get errors, they'd pile up */
+ sd.failed = TRUE;
+
+ tmp = g_slist_next(tmp);
+ }
+
+ g_slist_free(delete_list->data);
+
+ delete_list = g_slist_next(delete_list);
+ }
+
+ g_slist_free(cache->deleted);
+ cache->deleted = NULL;
+
+ g_hash_table_foreach(cache->cache, (GHFunc)cache_sync_foreach,
+ &sd);
+
+ return !sd.failed;
+}
+
+typedef struct _CleanData CleanData;
+struct _CleanData {
+ GTime now;
+ Cache* cache;
+ GTime length;
+};
+
+static gboolean
+cache_clean_foreach(const gchar* key,
+ Dir* dir, CleanData* cd)
+{
+ GTime last_access = dir_get_last_access(dir);
+
+ if ((cd->now - last_access) > cd->length)
+ {
+ dir_destroy(dir);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+void
+cache_clean (Cache *cache,
+ GTime older_than)
+{
+ CleanData cd = { 0, cache, older_than };
+
+ cd.now = time(NULL); /* ha ha, it's an online store! */
+
+ g_hash_table_foreach_remove(cache->cache, (GHRFunc)cache_clean_foreach,
+ &cd);
+}
+
+static void
+cache_delete_dir_by_pointer(Cache* cache,
+ Dir * d,
+ GConfError** err);
+
+static void
+cache_delete_recursive(Cache* cache, Dir* d, GSList** hit_list, GConfError** err)
+{
+ GSList* subdirs;
+ GSList* tmp;
+ gboolean failure = FALSE;
+
+ subdirs = dir_all_subdirs(d, err);
+
+ if (subdirs == NULL && err && *err != NULL)
+ failure = TRUE;
+
+ tmp = subdirs;
+ while (tmp != NULL && !failure)
+ {
+ Dir* subd;
+ gchar* fullkey;
+
+ fullkey = gconf_concat_key_and_dir(dir_get_name(d), (gchar*)tmp->data);
+
+ subd = cache_lookup(cache, fullkey, FALSE, err);
+
+ g_free(tmp->data);
+ g_free(fullkey);
+
+ if (subd == NULL && err && *err)
+ failure = TRUE;
+ else if (subd != NULL &&
+ !dir_is_deleted(subd))
+ {
+ /* recurse, whee! (unless the subdir is already deleted) */
+ cache_delete_dir_by_pointer(cache, subd, err);
+
+ if (err && *err)
+ failure = TRUE;
+ }
+
+ tmp = g_slist_next(tmp);
+ }
+
+ g_slist_free(subdirs);
+
+ /* The first directories to be deleted (fringes) go on the front
+ of the list. */
+ *hit_list = g_slist_prepend(*hit_list, d);
+
+ /* We go ahead and mark the dir deleted */
+ dir_mark_deleted(d);
+
+ /* be sure we set error if failure occurred */
+ g_return_if_fail( (!failure) || (err == NULL) || (*err != NULL));
+}
+
+
+static void
+cache_delete_dir_by_pointer(Cache* cache,
+ Dir * d,
+ GConfError** err)
+{
+ GSList* hit_list = NULL;
+
+ cache_delete_recursive(cache, d, &hit_list, err);
+
+ /* If you first dir_cache_delete() a subdir, then dir_cache_delete()
+ its parent, without syncing, first the list generated by
+ the subdir delete then the list from the parent delete should
+ be nuked. If you first delete a parent, then its subdir,
+ really only the parent list should be nuked, but
+ in effect it's OK to nuke the parent first then
+ fail to nuke the subdir. So, if we prepend here,
+ then nuke the list in order, it will work fine.
+ */
+
+ cache->deleted = g_slist_prepend(cache->deleted, hit_list);
+}
+
+void
+cache_delete_dir (Cache *cache,
+ const gchar *key,
+ GConfError **err)
+{
+ Dir* d;
+
+ d = cache_lookup(cache, key, FALSE, err);
+
+ if (d != NULL)
+ {
+ g_assert(err == NULL || *err == NULL);
+ cache_delete_dir_by_pointer(cache, d, err);
+ }
+}
+
+Dir*
+cache_lookup (Cache *cache,
+ const gchar *key,
+ gboolean create_if_missing,
+ GConfError **err)
+{
+ Dir* dir;
+
+ g_assert(key != NULL);
+
+ /* Check cache */
+ dir = g_hash_table_lookup(cache->cache, key);
+
+ if (dir != NULL)
+ {
+ return dir;
+ }
+ else
+ {
+ /* Not in cache, check whether we already failed
+ to load it */
+ if (cache_is_nonexistent(cache, key))
+ {
+ if (!create_if_missing)
+ return NULL;
+ }
+ else
+ {
+ /* Didn't already fail to load, try to load */
+ dir = dir_load(key, cache->root_dir, err);
+
+ if (dir != NULL)
+ {
+ g_assert(err == NULL || *err == NULL);
+
+ /* Cache it */
+ cache_insert(cache, dir);
+
+ return dir;
+ }
+ else
+ {
+ /* Remember that we failed to load it */
+ if (!create_if_missing)
+ {
+ cache_set_nonexistent(cache, key, TRUE);
+
+ return NULL;
+ }
+ else
+ {
+ if (err && *err)
+ {
+ gconf_error_destroy(*err);
+ *err = NULL;
+ }
+ }
+ }
+ }
+ }
+
+ g_assert(dir == NULL);
+ g_assert(create_if_missing);
+ g_assert(err == NULL || *err == NULL);
+
+ if (dir == NULL)
+ {
+ dir = dir_new(key, cache->root_dir);
+
+ if (!dir_ensure_exists(dir, err))
+ {
+ dir_destroy(dir);
+
+ g_return_val_if_fail((err == NULL) ||
+ (*err != NULL) ,
+ NULL);
+ return NULL;
+ }
+ else
+ cache_insert(cache, dir);
+ }
+
+ return dir;
+}
+
+static gboolean
+cache_is_nonexistent(Cache* cache,
+ const gchar* key)
+{
+ return GPOINTER_TO_INT(g_hash_table_lookup(cache->nonexistent_cache,
+ key));
+}
+
+static void
+cache_set_nonexistent (Cache* cache,
+ const gchar* key,
+ gboolean setting)
+{
+ if (setting)
+ {
+ /* don't use safe_ here, doesn't matter */
+ g_hash_table_insert(cache->nonexistent_cache,
+ g_strdup(key),
+ GINT_TO_POINTER(TRUE));
+ }
+ else
+ {
+ gpointer origkey;
+ gpointer origval;
+
+ if (g_hash_table_lookup_extended(cache->nonexistent_cache,
+ key,
+ &origkey, &origval))
+ {
+ g_free(origkey);
+ g_hash_table_remove(cache->nonexistent_cache,
+ key);
+ }
+ }
+}
+
+static void
+cache_insert (Cache* cache,
+ Dir* d)
+{
+ g_return_if_fail(d != NULL);
+ safe_g_hash_table_insert(cache->cache, (gchar*)dir_get_name(d), d);
+}
+
+static void
+cache_destroy_foreach(const gchar* key,
+ Dir* dir, gpointer data)
+{
+ dir_destroy(dir);
+}
+
+static void
+cache_destroy_nonexistent_foreach(gchar* key,
+ gpointer val,
+ gpointer data)
+{
+ g_free(key);
+}
+
+
+
+
diff --git a/backends/xml-cache.h b/backends/xml-cache.h
new file mode 100644
index 00000000..2191707e
--- /dev/null
+++ b/backends/xml-cache.h
@@ -0,0 +1,43 @@
+/* GConf
+ * Copyright (C) 1999 Red Hat Inc.
+ *
+ * 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_XML_CACHE_H
+#define GCONF_XML_CACHE_H
+
+#include <gconf/gconf.h>
+#include <gnome-xml/tree.h>
+#include "xml-dir.h"
+
+typedef struct _Cache Cache;
+
+Cache* cache_new (const gchar *root_dir);
+void cache_destroy (Cache *cache);
+gboolean cache_sync (Cache *cache,
+ GConfError **err);
+void cache_clean (Cache *cache,
+ GTime older_than);
+void cache_delete_dir (Cache *cache,
+ const gchar *key,
+ GConfError **err);
+Dir* cache_lookup (Cache *cache,
+ const gchar *key,
+ gboolean create_if_missing,
+ GConfError **err);
+
+#endif
diff --git a/backends/xml-dir.c b/backends/xml-dir.c
index a44fecc9..9d2a98b0 100644
--- a/backends/xml-dir.c
+++ b/backends/xml-dir.c
@@ -20,7 +20,60 @@
#include "xml-dir.h"
#include "xml-entry.h"
-typedef struct _Dir Dir;
+#include <gnome-xml/parser.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+#include <limits.h>
+
+#include <gconf/gconf-internals.h>
+#include "xml-entry.h"
+
+/* Quick hack so I can mark strings */
+
+#ifdef _
+#warning "_ already defined"
+#else
+#define _(x) x
+#endif
+
+#ifdef N_
+#warning "N_ already defined"
+#else
+#define N_(x) x
+#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);
+ }
+}
+#endif
+
+static gchar* parent_dir(const gchar* dir);
struct _Dir {
gchar* key;
@@ -42,19 +95,16 @@ static Entry* dir_make_new_entry(Dir* d, const gchar* relative_key);
static gboolean dir_forget_entry_if_useless(Dir* d, Entry* e);
-Dir*
-dir_new(const gchar *keyname,
- const gchar *xml_root_dir)
+static Dir*
+dir_blank(const gchar* key)
{
Dir* d;
d = g_new0(Dir, 1);
-
- d->key = g_strdup(keyname);
- d->fs_dirname = g_concat_key_and_dir(xml_root_dir, keyname);
- d->xml_filename = g_strconcat(d->fs_dirname, "/%gconf.xml", NULL);
- d->root_dir_len = strlen(xml_root_dir);
+ g_assert(gconf_valid_key(key, NULL));
+
+ d->key = g_strdup(key);
d->last_access = time(NULL);
d->doc = NULL;
@@ -67,6 +117,70 @@ dir_new(const gchar *keyname,
return d;
}
+Dir*
+dir_new(const gchar *keyname,
+ const gchar *xml_root_dir)
+{
+ Dir* d;
+
+ d = dir_blank(keyname);
+
+ /* sync with dir_load() */
+ d->fs_dirname = gconf_concat_key_and_dir(xml_root_dir, keyname);
+ d->xml_filename = g_strconcat(d->fs_dirname, "/%gconf.xml", NULL);
+ d->root_dir_len = strlen(xml_root_dir);
+
+ return d;
+}
+
+Dir*
+dir_load (const gchar* xml_root_dir, const gchar* key, GConfError** err)
+{
+ Dir* d;
+ gchar* fs_dirname;
+ gchar* xml_filename;
+
+ fs_dirname = gconf_concat_key_and_dir(xml_root_dir, key);
+ xml_filename = g_strconcat(fs_dirname, "/%gconf.xml", NULL);
+
+ {
+ struct stat s;
+ gboolean error = FALSE;
+
+ if (stat(xml_filename, &s) != 0)
+ {
+ gconf_set_error(err, GCONF_FAILED,
+ _("Could not stat `%s': %s"),
+ xml_filename, strerror(errno));
+ error = TRUE;
+ }
+ else if (S_ISDIR(s.st_mode))
+ {
+ gconf_set_error(err, GCONF_FAILED,
+ _("XML filename `%s' is a directory"),
+ xml_filename);
+ error = TRUE;
+ }
+
+ if (error)
+ {
+ g_free(fs_dirname);
+ g_free(xml_filename);
+ return NULL;
+ }
+ }
+
+ d = dir_blank(key);
+
+ /* sync with dir_new() */
+ d->fs_dirname = fs_dirname;
+ d->xml_filename = xml_filename;
+ d->root_dir_len = strlen(xml_root_dir);
+
+ return d;
+}
+
+
static void
entry_destroy_foreach(const gchar* name, Entry* e, gpointer data)
{
@@ -99,11 +213,11 @@ gboolean
dir_ensure_exists (Dir* d,
GConfError** err)
{
- if (!create_fs_dir(d->fs_dirname, d->xml_filename, err))
+ if (!create_fs_dir(d->fs_dirname, d->xml_filename, d->root_dir_len, err))
{
/* check that error is set */
- g_return_val_if_fail( (err == NULL) || (*err != NULL), NULL );
+ g_return_val_if_fail( (err == NULL) || (*err != NULL), FALSE );
return FALSE;
}
@@ -114,7 +228,7 @@ dir_ensure_exists (Dir* d,
static void
entry_sync_foreach(const gchar* name, Entry* e, gpointer data)
{
- entry_sync(e);
+ entry_sync_to_node(e);
}
gboolean
@@ -171,7 +285,7 @@ dir_sync (Dir* d, GConfError** err)
/* Try to solve the problem by creating the FS dir */
if (!gconf_file_exists(d->fs_dirname))
{
- if (create_fs_dir(d->fs_dirname, NULL, d->source->root_dir, err))
+ if (create_fs_dir(d->fs_dirname, NULL, d->root_dir_len, err))
{
if (xmlSaveFile(tmp_filename, d->doc) >= 0)
recovered = TRUE;
@@ -266,7 +380,7 @@ dir_set_value (Dir* d, const gchar* relative_key,
if (e == NULL)
e = dir_make_new_entry(d, relative_key);
- entry_set(e, value);
+ entry_set_value(e, value);
d->last_access = time(NULL);
entry_set_mod_time(e, d->last_access);
@@ -309,7 +423,7 @@ dir_get_value (Dir* d,
g_assert(e != NULL);
- val = entry_get_value(e, locales);
+ val = entry_get_value(e, locales, err);
/* Fill schema name if value is NULL because we might be
interested in the default value of the key in that case. */
@@ -326,10 +440,16 @@ dir_get_value (Dir* d,
}
}
+const gchar*
+dir_get_name (Dir *d)
+{
+ g_return_val_if_fail(d != NULL, NULL);
+ return d->key;
+}
+
GConfMetaInfo*
dir_get_metainfo(Dir* d, const gchar* relative_key, GConfError** err)
{
- GConfMetaInfo* gcmi;
Entry* e;
d->last_access = time(NULL);
@@ -373,7 +493,7 @@ dir_unset_value (Dir* d, const gchar* relative_key,
if (e == NULL) /* nothing to change */
return;
- if (entry_unset(e, locale))
+ if (entry_unset_value(e, locale))
{
/* If entry_unset() returns TRUE then
the entry was changed (not already unset) */
@@ -406,16 +526,24 @@ listify_foreach(const gchar* key, Entry* e, ListifyData* ld)
{
GConfValue* val;
GConfEntry* entry;
+ GConfError* error = NULL;
- val = entry_get_value(e, ld->locales);
+ val = entry_get_value(e, ld->locales, &error);
+ if (error != NULL)
+ {
+ g_assert(val == NULL);
+ gconf_error_destroy(error);
+ return;
+ }
+
entry = gconf_entry_new_nocopy(g_strdup(key),
val ? gconf_value_copy(val) : NULL);
if (val == NULL &&
- e->schema_name)
+ entry_get_schema_name(e))
{
- gconf_entry_set_schema_name(entry, e->schema_name);
+ gconf_entry_set_schema_name(entry, entry_get_schema_name(e));
}
ld->list = g_slist_prepend(ld->list, entry);
@@ -582,7 +710,7 @@ dir_last_access (Dir* d)
/* private Dir functions */
static void
-dir_fill_cache_from_doc(Dir* d);
+dir_fill_cache_from_doc(Dir* d);
static void
dir_load_doc(Dir* d, GConfError** err)
@@ -700,8 +828,8 @@ dir_make_new_entry(Dir* d, const gchar* relative_key)
entry_set_node(e, xmlNewChild(d->doc->root, NULL, "entry", NULL));
- safe_g_hash_table_insert(d->entry_cache, entry_get_name(e), e);
-
+ safe_g_hash_table_insert(d->entry_cache, (gchar*)entry_get_name(e), e);
+
return e;
}
@@ -713,7 +841,7 @@ dir_forget_entry_if_useless(Dir* d, Entry* e)
if (entry_get_schema_name(e) != NULL)
return FALSE;
- val = entry_get_value(e, NULL);
+ val = entry_get_value(e, NULL, NULL);
if (val != NULL)
return FALSE; /* not useless */
@@ -725,6 +853,14 @@ dir_forget_entry_if_useless(Dir* d, Entry* e)
return TRUE;
}
+static void
+dir_fill_cache_from_doc(Dir* d)
+{
+
+ /* FIXME */
+
+}
+
/*
* Misc
*/
@@ -798,3 +934,38 @@ create_fs_dir(const gchar* dir, const gchar* xml_filename,
return TRUE;
}
+
+static gchar*
+parent_dir(const gchar* dir)
+{
+ /* We assume the dir doesn't have a trailing slash, since that's our
+ standard canonicalization in GConf */
+ gchar* parent;
+ gchar* last_slash;
+
+ g_return_val_if_fail(*dir != '\0', NULL);
+
+ if (dir[1] == '\0')
+ {
+ g_assert(dir[0] == '/');
+ return NULL;
+ }
+
+ parent = g_strdup(dir);
+
+ last_slash = strrchr(parent, '/');
+
+ /* dir must have had at least the root slash in it */
+ g_assert(last_slash != NULL);
+
+ if (last_slash != parent)
+ *last_slash = '\0';
+ else
+ {
+ ++last_slash;
+ *last_slash = '\0';
+ }
+
+ return parent;
+}
+
diff --git a/backends/xml-dir.h b/backends/xml-dir.h
index 6fde7fe9..630c91b8 100644
--- a/backends/xml-dir.h
+++ b/backends/xml-dir.h
@@ -26,58 +26,53 @@
/* Dir stores the information about a given directory */
typedef struct _Dir Dir;
-
-Dir* dir_new (const gchar *keyname,
- const gchar *xml_root_dir);
-
-void dir_destroy (Dir *d);
-
-gboolean dir_ensure_exists (Dir *d,
- GConfError **err);
-
-gboolean dir_sync (Dir *d,
- GConfError **err);
-
+Dir* dir_new (const gchar *keyname,
+ const gchar *xml_root_dir);
+Dir* dir_load (const gchar *key,
+ const gchar *xml_root_dir,
+ GConfError **err);
+void dir_destroy (Dir *d);
+gboolean dir_ensure_exists (Dir *d,
+ GConfError **err);
+gboolean dir_sync (Dir *d,
+ GConfError **err);
+
+const gchar* dir_get_name (Dir *d);
/* key should have no slashes in it */
-void dir_set_value (Dir *d,
- const gchar *relative_key,
- GConfValue *value,
- GConfError **err);
-
-GConfValue* dir_get_value (Dir *d,
- const gchar *relative_key,
- const gchar **locales,
- gchar **schema_name,
- GConfError **err);
+void dir_set_value (Dir *d,
+ const gchar *relative_key,
+ GConfValue *value,
+ GConfError **err);
+GConfValue* dir_get_value (Dir *d,
+ const gchar *relative_key,
+ const gchar **locales,
+ gchar **schema_name,
+ GConfError **err);
+GConfMetaInfo* dir_get_metainfo (Dir *d,
+ const gchar *relative_key,
+ GConfError **err);
+void dir_unset_value (Dir *d,
+ const gchar *relative_key,
+ const gchar *locale,
+ GConfError **err);
+GSList* dir_all_entries (Dir *d,
+ const gchar **locales,
+ GConfError **err);
+GSList* dir_all_subdirs (Dir *d,
+ GConfError **err);
+void dir_set_schema (Dir *d,
+ const gchar *relative_key,
+ const gchar *schema_key,
+ GConfError **err);
+GTime dir_get_last_access (Dir *d);
-GConfMetaInfo* dir_get_metainfo (Dir *d,
- const gchar *relative_key,
- GConfError **err);
-
-void dir_unset_value (Dir *d,
- const gchar *relative_key,
- const gchar *locale,
- GConfError **err);
-
-GSList* dir_all_entries (Dir *d,
- const gchar **locales,
- GConfError **err);
-
-GSList* dir_all_subdirs (Dir *d,
- GConfError **err);
-
-void dir_set_schema (Dir *d,
- const gchar *relative_key,
- const gchar *schema_key,
- GConfError **err);
-
-GTime dir_get_last_access (Dir *d);
/* Marks for deletion; dir cache really has to implement directory
deletion, since it is recursive */
-void dir_mark_deleted (Dir *d);
-gboolean dir_is_deleted (Dir *d);
+void dir_mark_deleted (Dir *d);
+gboolean dir_is_deleted (Dir *d);
+
#endif
diff --git a/backends/xml-entry.c b/backends/xml-entry.c
index df9be270..6e1d38c9 100644
--- a/backends/xml-entry.c
+++ b/backends/xml-entry.c
@@ -18,6 +18,23 @@
*/
#include "xml-entry.h"
+#include <gconf/gconf-internals.h>
+#include <stdlib.h>
+
+/* Quick hack so I can mark strings */
+
+#ifdef _
+#warning "_ already defined"
+#else
+#define _(x) x
+#endif
+
+#ifdef N_
+#warning "N_ already defined"
+#else
+#define N_(x) x
+#endif
+
struct _Entry {
gchar* name; /* a relative key */
@@ -88,9 +105,10 @@ entry_get_node (Entry*e)
GConfValue*
entry_get_value(Entry* e, const gchar** locales, GConfError** err)
{
- g_return_if_fail(e != NULL);
+ g_return_val_if_fail(e != NULL, NULL);
/* FIXME */
+ return NULL;
}
void
@@ -103,10 +121,10 @@ entry_set_value(Entry* e, GConfValue* value)
}
gboolean
-entry_unset_value (Entry *entry,
+entry_unset_value (Entry *e,
const gchar *locale)
{
- g_return_if_fail(e != NULL);
+ g_return_val_if_fail(e != NULL, FALSE);
/* FIXME */
e->dirty = TRUE;
@@ -119,7 +137,7 @@ entry_get_metainfo(Entry* e)
{
GConfMetaInfo* gcmi;
- g_return_if_fail(e != NULL);
+ g_return_val_if_fail(e != NULL, NULL);
gcmi = gconf_meta_info_new();
@@ -180,16 +198,31 @@ entry_set_mod_user (Entry *e,
* XML-related cruft
*/
-void my_xmlSetProp(xmlNodePtr node,
- const gchar* name,
- const gchar* str);
+static void my_xmlSetProp(xmlNodePtr node,
+ const gchar* name,
+ const gchar* str);
-char* my_xmlGetProp(xmlNodePtr node,
- const gchar* name);
+static char* my_xmlGetProp(xmlNodePtr node,
+ const gchar* name);
static GConfValue*
node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err);
+static xmlNodePtr
+find_schema_subnode_by_locale(xmlNodePtr node, const gchar* locale);
+
+static void
+entry_sync_if_needed(Entry* e, GConfValue* val)
+{
+ if (!e->dirty)
+ return;
+
+ if (e->cached_value &&
+ e->cached_value->type == GCONF_VALUE_SCHEMA)
+ {
+ entry_sync_to_node(e);
+ }
+}
void
entry_fill_from_node(Entry* e, const gchar* name)
@@ -265,8 +298,8 @@ entry_fill_from_node(Entry* e, const gchar* name)
if (e->cached_value != NULL)
gconf_value_destroy(e->cached_value);
- e->cached_value = xentry_extract_value(e->node, NULL, /* FIXME current locale as a guess */
- &error);
+ e->cached_value = node_extract_value(e->node, NULL, /* FIXME current locale as a guess */
+ &error);
if (e->cached_value)
{
@@ -856,7 +889,7 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err)
/* What the hell is this? */
gconf_log(GCL_WARNING,
_("Didn't understand XML node <%s> inside an XML list node"),
- iter->name ? iter->name : "???");
+ iter->name ? iter->name : (guchar*)"???");
}
if (v != NULL)
@@ -881,7 +914,6 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err)
GConfValue* car = NULL;
GConfValue* cdr = NULL;
xmlNodePtr iter;
- GSList* bad_nodes = NULL;
iter = node->childs;
@@ -939,7 +971,7 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err)
/* What the hell is this? */
gconf_log(GCL_WARNING,
_("Didn't understand XML node <%s> inside an XML pair node"),
- iter->name ? iter->name : "???");
+ iter->name ? (gchar*)iter->name : "???");
}
}
iter = iter->next;
@@ -965,7 +997,7 @@ node_extract_value(xmlNodePtr node, const gchar** locales, GConfError** err)
*/
/* makes setting to NULL or empty string equal to unset */
-void
+static void
my_xmlSetProp(xmlNodePtr node,
const gchar* name,
const gchar* str)
@@ -1001,7 +1033,7 @@ my_xmlSetProp(xmlNodePtr node,
}
/* Makes empty strings equal to "unset" */
-char*
+static char*
my_xmlGetProp(xmlNodePtr node,
const gchar* name)
{