[dconf] add support for flattening a dconf db to a GTree



commit b0c706ef7da2120936ea6effe3d8166825f4ca8f
Author: Ryan Lortie <desrt desrt ca>
Date:   Tue Aug 11 19:40:51 2009 -0400

    add support for flattening a dconf db to a GTree
    
      also add a dump() debug function to display the contents of the entire
      tree to stderr and wire it up to the dbus "Dump" method.

 writer/Makefile.am            |    1 +
 writer/dconf-dbus-writer.c    |    6 ++
 writer/dconf-writer-flatten.c |  124 +++++++++++++++++++++++++++++++++++++++++
 writer/dconf-writer-private.h |    7 ++
 writer/dconf-writer.c         |   24 +++++++-
 writer/dconf-writer.h         |    2 +
 6 files changed, 161 insertions(+), 3 deletions(-)
---
diff --git a/writer/Makefile.am b/writer/Makefile.am
index 44f64bc..2027f83 100644
--- a/writer/Makefile.am
+++ b/writer/Makefile.am
@@ -6,6 +6,7 @@ DEFS = -DDCONF_CONF=\"$(sysconfdir)/dconf/dconf.conf\"
 noinst_LIBRARIES = libdconf-writer.a
 
 libdconf_writer_a_SOURCES = \
+	dconf-writer-flatten.c	\
 	dconf-writer-file.c	\
 	dconf-writer.c		\
 	dconf-writer-merge.c	\
diff --git a/writer/dconf-dbus-writer.c b/writer/dconf-dbus-writer.c
index b4d136e..defdafb 100644
--- a/writer/dconf-dbus-writer.c
+++ b/writer/dconf-dbus-writer.c
@@ -353,6 +353,12 @@ dconf_dbus_writer_handle_message (DConfDBusWriter *writer)
       return dconf_dbus_writer_reply (writer, status, &sequence, error);
     }
 
+  if (dconf_dbus_writer_is_call (writer, "Dump", ""))
+    {
+      dconf_writer_dump (writer->writer);
+      return dconf_dbus_writer_reply (writer, TRUE, NULL, NULL);
+    }
+
   return NULL;
 }
 
diff --git a/writer/dconf-writer-flatten.c b/writer/dconf-writer-flatten.c
new file mode 100644
index 0000000..ee6fe01
--- /dev/null
+++ b/writer/dconf-writer-flatten.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright © 2009 Codethink Limited
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of version 3 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * See the included COPYING file for more information.
+ *
+ * Authors: Ryan Lortie <desrt desrt ca>
+ */
+
+#include "dconf-writer-private.h"
+
+#include <string.h>
+
+static gboolean
+dconf_writer_check_name (const gchar *name,
+                         guint32      namelen,
+                         gboolean    *is_directory)
+{
+  gint i;
+
+  if (namelen == 0)
+    return FALSE;
+
+  if (namelen == 1 && name[0] == '/')
+    return FALSE;
+
+  for (i = 0; i < namelen - 1; i++)
+    if (name[i] == '/')
+      return FALSE;
+
+  *is_directory = name[i] == '/';
+
+  return TRUE;
+}
+
+static void
+dconf_writer_flatten_index (DConfWriter *writer,
+                            GTree       *tree,
+                            const gchar *prefix,
+                            gint         prefixlen,
+                            guint32      index)
+{
+  const volatile struct dir_entry *entries;
+  gint n_items;
+  gint i;
+
+  entries = dconf_writer_get_dir (writer, index, &n_items);
+
+  for (i = 0; i < n_items; i++)
+    {
+      const volatile struct dir_entry *entry = &entries[i];
+      gboolean is_directory;
+      const gchar *name;
+      guint32 namelen;
+      gint pathlen;
+      gchar *path;
+
+      name = dconf_writer_get_entry_name (writer, entry, &namelen);
+
+      if (!dconf_writer_check_name (name, namelen, &is_directory))
+        continue;
+
+      pathlen = prefixlen + namelen;
+      path = g_malloc (pathlen + 1);
+      memcpy (path, prefix, prefixlen);
+      memcpy (path + prefixlen, name, namelen);
+      path[pathlen] = '\0';
+
+      if (is_directory)
+        {
+          index = dconf_writer_get_index (writer, &entry->data.index, TRUE);
+          dconf_writer_flatten_index (writer, tree, path, pathlen, index);
+          g_free (path);
+        }
+      else
+        {
+          g_tree_insert (tree, path,
+                         dconf_writer_get_entry_value (writer, entry));
+        }
+    }
+}
+
+GTree *
+dconf_writer_flatten (DConfWriter *writer)
+{
+  GTree *tree;
+
+  tree = g_tree_new_full ((GCompareDataFunc) strcmp, NULL,
+                          g_free, (GDestroyNotify) g_variant_unref);
+
+  dconf_writer_flatten_index (writer, tree, "", 0,
+                              writer->data.super->root_index);
+
+  return tree;
+}
+
+static gboolean
+dconf_writer_dump_entry (gpointer key,
+                         gpointer value,
+                         gpointer user_data)
+{
+  GString *string;
+
+  string = g_variant_markup_print (value, NULL, 0, 0, 0);
+  g_message ("  %s = %s", (const gchar *) key, string->str);
+  g_string_free (string, TRUE);
+
+  return FALSE;
+}
+
+void
+dconf_writer_dump (DConfWriter *writer)
+{
+  GTree *tree;
+
+  tree = dconf_writer_flatten (writer);
+  g_message ("dumping contents of dconf database");
+  g_tree_foreach (tree, dconf_writer_dump_entry, NULL);
+  g_message ("end of output");
+  g_tree_unref (tree);
+}
diff --git a/writer/dconf-writer-private.h b/writer/dconf-writer-private.h
index 20af829..bbdfb60 100644
--- a/writer/dconf-writer-private.h
+++ b/writer/dconf-writer-private.h
@@ -83,4 +83,11 @@ gboolean
 dconf_writer_create (DConfWriter  *writer,
                      GError      **error);
 
+GVariant *
+dconf_writer_get_entry_value (DConfWriter                     *writer,
+                              const volatile struct dir_entry *entry);
+
+GTree *
+dconf_writer_flatten (DConfWriter *writer);
+
 #endif /* _dconf_writer_private_h_ */
diff --git a/writer/dconf-writer.c b/writer/dconf-writer.c
index cbb3918..022ff63 100644
--- a/writer/dconf-writer.c
+++ b/writer/dconf-writer.c
@@ -58,7 +58,7 @@ dconf_writer_allocate (DConfWriter *writer,
 }
 
 static volatile void *
-dconf_writer_get_block (DConfWriter *writer,
+dconf_writer_get_chunk (DConfWriter *writer,
                         guint32      index,
                         guint32     *size)
 {
@@ -105,7 +105,7 @@ dconf_writer_get_dir (DConfWriter *writer,
   volatile struct dir_entry *entries;
   guint32 size;
 
-  entries = dconf_writer_get_block (writer, index, &size);
+  entries = dconf_writer_get_chunk (writer, index, &size);
 
   if (size % sizeof (struct dir_entry))
     size = 0;
@@ -208,7 +208,7 @@ dconf_writer_get_entry_name (DConfWriter                     *writer,
                              guint32                         *name_length)
 {
   if G_UNLIKELY (entry->namelen > sizeof entry->name.direct)
-    return (const gchar *) dconf_writer_get_block (writer,
+    return (const gchar *) dconf_writer_get_chunk (writer,
                                                    entry->name.index,
                                                    name_length);
 
@@ -249,3 +249,21 @@ dconf_writer_set (DConfWriter  *writer,
 
   return dconf_writer_merge (writer, key, &empty_string, &value, 1, error);
 }
+
+GVariant *
+dconf_writer_get_entry_value (DConfWriter                     *writer,
+                              const volatile struct dir_entry *entry)
+{
+  const volatile void *data;
+  guint32 index;
+  guint32 size;
+
+  g_assert (entry->type == 'v');
+
+  index = dconf_writer_get_index (writer, &entry->data.index, TRUE);
+  data = dconf_writer_get_chunk (writer, entry->data.index, &size);
+
+  return g_variant_ref_sink (g_variant_from_data (NULL,
+                                                  (gconstpointer) data, size,
+                                                  0, NULL, NULL));
+}
diff --git a/writer/dconf-writer.h b/writer/dconf-writer.h
index 544ba36..a59b54b 100644
--- a/writer/dconf-writer.h
+++ b/writer/dconf-writer.h
@@ -41,4 +41,6 @@ gboolean                dconf_writer_merge                              (DConfWr
                                                                          gint          n_items,
                                                                          GError      **error);
 
+void                    dconf_writer_dump                               (DConfWriter  *writer);
+
 #endif /* _dconf_writer_h_ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]