summaryrefslogtreecommitdiff
path: root/service/dconf-writer.c
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2010-07-15 21:18:55 -0400
committerRyan Lortie <desrt@desrt.ca>2010-07-15 21:30:53 -0400
commite7fd6d849feaea45d76cda1eb074c9ea59b85637 (patch)
treeee014c5ab816989bf19c730f16373359453bb2e0 /service/dconf-writer.c
parentc37c49a0c25505e0136158b56aba3703db0fa828 (diff)
downloaddconf-e7fd6d849feaea45d76cda1eb074c9ea59b85637.tar.gz
Many improvements
- support the notion of 'profiles' This is how we will configure layering of databases in dconf. It's not wired-up yet (except to choose the name of the user database). - support multiple writers in the service Using the (very freshly API-broken) GDBus subtree support. Introspection returns the names of existing databases, but any object path can be used to create a new database. - support the start of the 'shm' file Used to prevent the reader from reopening the gvdb every time. dconf reads now involve zero system calls in the usual case. The server is queried on startup for the location of the shm files. By default, this is in ~/.cache/dconf/ for now. This won't work properly on NFS, but it's a start.
Diffstat (limited to 'service/dconf-writer.c')
-rw-r--r--service/dconf-writer.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/service/dconf-writer.c b/service/dconf-writer.c
new file mode 100644
index 0000000..a165ed5
--- /dev/null
+++ b/service/dconf-writer.c
@@ -0,0 +1,166 @@
+#include "dconf-writer.h"
+
+#include "dconf-rebuilder.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+
+static const gchar *dconf_writer_shm_dir;
+static const gchar *dconf_writer_db_dir;
+
+struct OPAQUE_TYPE__DConfWriter
+{
+ gchar *path;
+ gchar *shm;
+};
+
+const gchar *
+dconf_writer_get_shm_dir (void)
+{
+ return dconf_writer_shm_dir;
+}
+
+/* Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_"
+ */
+static gboolean
+is_valid_dbus_path_element (const gchar *string)
+{
+ gint i;
+
+ for (i = 0; string[i]; i++)
+ if (!g_ascii_isalnum (string[i]) && string[i] != '_')
+ return FALSE;
+
+ return TRUE;
+}
+
+gchar **
+dconf_writer_list_existing (void)
+{
+ GPtrArray *array;
+ GDir *dir;
+
+ array = g_ptr_array_new ();
+
+ if ((dir = g_dir_open ("/home/desrt/.config/dconf", 0, NULL)))
+ {
+ const gchar *name;
+
+ while ((name = g_dir_read_name (dir)))
+ if (is_valid_dbus_path_element (name))
+ g_ptr_array_add (array, g_strdup (name));
+ }
+
+ g_ptr_array_add (array, NULL);
+
+ return (gchar **) g_ptr_array_free (array, FALSE);
+}
+
+static void
+dconf_writer_touch_shm (DConfWriter *writer)
+{
+ gchar one = 1;
+ gint fd;
+
+ fd = open (writer->shm, O_WRONLY);
+ write (fd, &one, sizeof one);
+ close (fd);
+
+ unlink (writer->shm);
+}
+
+gboolean
+dconf_writer_write (DConfWriter *writer,
+ const gchar *name,
+ GVariant *value,
+ GError **error)
+{
+ if (!dconf_rebuilder_rebuild (writer->path, "", &name, &value, 1, error))
+ return FALSE;
+
+ dconf_writer_touch_shm (writer);
+
+ return TRUE;
+}
+
+gboolean
+dconf_writer_write_many (DConfWriter *writer,
+ const gchar *prefix,
+ const gchar * const *keys,
+ GVariant * const *values,
+ gsize n_items,
+ GError **error)
+{
+ if (!dconf_rebuilder_rebuild (writer->path, prefix, keys,
+ values, n_items, error))
+ return FALSE;
+
+ dconf_writer_touch_shm (writer);
+
+ return TRUE;
+}
+
+DConfWriter *
+dconf_writer_new (const gchar *name)
+{
+ DConfWriter *writer;
+
+ writer = g_slice_new (DConfWriter);
+ writer->path = g_build_filename (dconf_writer_db_dir, name, NULL);
+ writer->shm = g_build_filename (dconf_writer_shm_dir, name, NULL);
+
+ return writer;
+}
+
+void
+dconf_writer_init (void)
+{
+ const gchar *config_dir = g_get_user_config_dir ();
+ const gchar *cache_dir = g_get_user_cache_dir ();
+
+ dconf_writer_db_dir = g_build_filename (config_dir, "dconf", NULL);
+
+ if (g_mkdir_with_parents (dconf_writer_db_dir, 0700))
+ {
+ /* XXX remove this after a while... */
+ if (errno == ENOTDIR)
+ {
+ gchar *tmp, *final;
+
+ g_message ("Attempting to migrate ~/.config/dconf "
+ "to ~/.config/dconf/user");
+
+ tmp = g_build_filename (config_dir, "dconf-user.db", NULL);
+
+ if (rename (dconf_writer_db_dir, tmp))
+ g_error ("Can not rename '%s' to '%s': %s",
+ dconf_writer_db_dir, tmp, g_strerror (errno));
+
+ if (g_mkdir_with_parents (dconf_writer_db_dir, 0700))
+ g_error ("Can not create directory '%s': %s",
+ dconf_writer_db_dir, g_strerror (errno));
+
+ final = g_build_filename (dconf_writer_db_dir, "user", NULL);
+
+ if (rename (tmp, final))
+ g_error ("Can not rename '%s' to '%s': %s",
+ tmp, final, g_strerror (errno));
+
+ g_message ("Successful.");
+
+ g_free (final);
+ g_free (tmp);
+ }
+ else
+ g_error ("Can not create directory '%s': %s",
+ dconf_writer_db_dir, g_strerror (errno));
+ }
+
+ dconf_writer_shm_dir = g_build_filename (cache_dir, "dconf", NULL);
+
+ if (g_mkdir_with_parents (dconf_writer_shm_dir, 0700))
+ g_error ("Can not create directory '%s': %s",
+ dconf_writer_shm_dir, g_strerror (errno));
+}