[dconf] prevent sets from succeeding on locked keys



commit 3aef08011ab8048d98adcd6b8ed1df81aa897675
Author: Ryan Lortie <desrt desrt ca>
Date:   Thu Oct 1 11:05:03 2009 -0400

    prevent sets from succeeding on locked keys
    
    partially implemented.

 dconf/dconf-core.c   |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++
 dconf/dconf-reader.c |   38 ++++++++++++++++++++---
 dconf/dconf-reader.h |   38 ++++++++++++-----------
 3 files changed, 136 insertions(+), 23 deletions(-)
---
diff --git a/dconf/dconf-core.c b/dconf/dconf-core.c
index 30cb9c9..660fcb8 100644
--- a/dconf/dconf-core.c
+++ b/dconf/dconf-core.c
@@ -295,6 +295,63 @@ dconf_get_writable (const gchar *path)
   return writable;
 }
 
+static gboolean
+dconf_check_writable (DConfMount   *mount,
+                      const gchar  *key,
+                      GError      **error)
+{
+  gboolean writable = TRUE;
+  gint i;
+
+  for (i = 0; writable && i < mount->n_dbs; i++)
+    writable = dconf_reader_get_writable (mount->dbs[i]->reader, key);
+
+  if (!writable)
+    {
+      g_set_error (error, 0, 0,
+                   "this key is locked");
+    }
+
+  return writable;
+}
+
+
+static gboolean
+dconf_check_tree_writable (DConfMount   *mount,
+                           const gchar  *prefix,
+                           GTree        *tree,
+                           GError      **error)
+{
+  const gchar * const *const_items;
+  gboolean writable = TRUE;
+  gchar **items;
+  gint length;
+  gint i;
+
+  length = g_tree_nnodes (tree);
+  items = g_new (gchar *, length + 1);
+  const_items = (const gchar * const *) items;
+
+  {
+    gchar **ptr;
+    g_tree_foreach (tree, append_to_array, &ptr);
+    *ptr = NULL;
+  }
+
+  for (i = 0; writable && i < mount->n_dbs; i++)
+    writable = dconf_reader_get_several_writable (mount->dbs[i]->reader,
+                                                  prefix, const_items);
+  g_strfreev (items);
+
+  if (!writable)
+    {
+      g_set_error (error, 0, 0,
+                   "one or more keys are locked");
+    }
+
+  return writable;
+}
+
 /**
  * dconf_watch:
  * @match: a key or path to watch
@@ -466,6 +523,9 @@ dconf_merge (const gchar  *prefix,
   mount = dconf_demux_path (&prefix, TRUE, NULL);
   g_assert (mount);
 
+  if (!dconf_check_tree_writable (mount, prefix, tree, error))
+    return FALSE;
+
   return dconf_dbus_merge (mount->dbs[0]->bus, prefix, tree, event_id, error);
 }
 
@@ -500,6 +560,16 @@ dconf_merge_async (const gchar             *prefix,
   mount = dconf_demux_path (&prefix, TRUE, NULL);
   g_assert (mount);
 
+  {
+    GError *error = NULL;
+
+    if (!dconf_check_tree_writable (mount, prefix, tree, &error))
+      {
+        g_assert_not_reached ();
+        // XXX dispatch in idle...
+      }
+  }
+
   dconf_dbus_merge_async (mount->dbs[0]->bus, prefix, tree,
                           (DConfDBusAsyncReadyCallback) callback,
                           user_data);
@@ -539,6 +609,9 @@ dconf_set (const gchar  *key,
   if ((mount = dconf_demux_path (&key, TRUE, error)) == NULL)
     return FALSE;
 
+  if (!dconf_check_writable (mount, key, error))
+    return FALSE;
+
   return dconf_dbus_set (mount->dbs[0]->bus, key, value, event_id, error);
 }
 
@@ -556,6 +629,16 @@ dconf_set_async (const gchar             *key,
   mount = dconf_demux_path (&key, TRUE, NULL);
   g_assert (mount);
 
+  {
+    GError *error = NULL;
+
+    if (!dconf_check_writable (mount, key, &error))
+      {
+        g_assert_not_reached ();
+        // XXX dispatch in idle...
+      }
+  }
+
   dconf_dbus_set_async (mount->dbs[0]->bus, key, value,
                         (DConfDBusAsyncReadyCallback) callback,
                         user_data);
diff --git a/dconf/dconf-reader.c b/dconf/dconf-reader.c
index a6d26ab..395d981 100644
--- a/dconf/dconf-reader.c
+++ b/dconf/dconf-reader.c
@@ -389,19 +389,18 @@ gboolean
 dconf_reader_get_writable (DConfReader *reader,
                            const gchar *name)
 {
-  const volatile struct dir_entry *entry;
   gboolean locked = FALSE;
 
   if (!dconf_reader_ensure_valid (reader))
     return FALSE;
 
   if (reader->data.super->flags & DCONF_FLAG_LOCKED)
-    locked = TRUE;
+    return FALSE;
 
   if (*name)
-    entry = dconf_reader_get_entry (reader, name,
-                                    reader->data.super->root_index,
-                                    &locked);
+    dconf_reader_get_entry (reader, name,
+                            reader->data.super->root_index,
+                            &locked);
 
   return !locked;
 }
@@ -428,3 +427,32 @@ dconf_reader_get_locked (DConfReader *reader,
   else
     return (reader->data.super->flags & DCONF_FLAG_LOCKED) != 0;
 }
+
+gboolean
+dconf_reader_get_several_writable (DConfReader         *reader,
+                                   const gchar         *name,
+                                   const gchar * const *items)
+{
+  const volatile struct dir_entry *entry;
+  gboolean locked = FALSE;
+
+  if (!dconf_reader_ensure_valid (reader))
+    return FALSE;
+
+  entry = dconf_reader_get_entry (reader, name,
+                                  reader->data.super->root_index,
+                                  &locked);
+
+  if (items[0][0] == '\0')
+    {
+      g_assert (items[1] == NULL);
+
+      return !locked;
+    }
+
+  /* not *the* most efficient way possible, but simple. */
+  while (!locked && *items != NULL)
+    dconf_reader_get_entry (reader, *items++, entry->data.index, &locked);
+
+  return !locked;
+}
diff --git a/dconf/dconf-reader.h b/dconf/dconf-reader.h
index c691368..098e1a5 100644
--- a/dconf/dconf-reader.h
+++ b/dconf/dconf-reader.h
@@ -18,23 +18,25 @@
 
 #include <glib.h>
 
-DConfReader *           dconf_reader_new                                (const gchar  *filename);
-
-void                    dconf_reader_get                                (DConfReader  *reader,
-                                                                         const gchar  *key,
-                                                                         GVariant    **value,
-                                                                         gboolean     *locked);
-
-void                    dconf_reader_list                               (DConfReader  *reader,
-                                                                         const gchar  *path,
-                                                                         GTree        *builder,
-                                                                         gboolean     *locked);
-
-gboolean                dconf_reader_get_locked                         (DConfReader  *reader,
-                                                                         const gchar  *name);
-
-gboolean                dconf_reader_get_writable                       (DConfReader  *reader,
-                                                                         const gchar  *name);
-
+DConfReader *           dconf_reader_new                                (const gchar         *filename);
+
+void                    dconf_reader_get                                (DConfReader         *reader,
+                                                                         const gchar         *key,
+                                                                         GVariant           **value,
+                                                                         gboolean            *locked);
+
+void                    dconf_reader_list                               (DConfReader         *reader,
+                                                                         const gchar         *path,
+                                                                         GTree               *builder,
+                                                                         gboolean            *locked);
+
+gboolean                dconf_reader_get_locked                         (DConfReader         *reader,
+                                                                         const gchar         *name);
+
+gboolean                dconf_reader_get_writable                       (DConfReader         *reader,
+                                                                         const gchar         *name);
+gboolean                dconf_reader_get_several_writable               (DConfReader         *reader,
+                                                                         const gchar         *prefix,
+                                                                         const gchar * const *items);
 
 #endif /* _dconf_reader_h_ */



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