PolicyKit: Branch 'wip/js-rule-files'

David Zeuthen david at kemper.freedesktop.org
Mon May 21 07:45:51 PDT 2012


 src/polkitbackend/polkitbackendjsauthority.c          |  186 +++++++++++-------
 test/data/etc/polkit-1/rules.d/10-testing.rules       |    2 
 test/data/usr/share/polkit-1/rules.d/10-testing.rules |    5 
 test/polkitbackend/test-polkitbackendjsauthority.c    |   14 -
 4 files changed, 139 insertions(+), 68 deletions(-)

New commits:
commit 89865529ec98067ba8eada3b59938204534de7b2
Author: David Zeuthen <davidz at redhat.com>
Date:   Mon May 21 10:45:08 2012 -0400

    Also load rules from /usr/share/polkit/rules.d
    
    ... in addition to /etc/polkit/rules.d.
    
    Signed-off-by: David Zeuthen <davidz at redhat.com>

diff --git a/src/polkitbackend/polkitbackendjsauthority.c b/src/polkitbackend/polkitbackendjsauthority.c
index 1d6e156..849034a 100644
--- a/src/polkitbackend/polkitbackendjsauthority.c
+++ b/src/polkitbackend/polkitbackendjsauthority.c
@@ -56,8 +56,8 @@
 
 struct _PolkitBackendJsAuthorityPrivate
 {
-  gchar *rules_dir;
-  GFileMonitor *dir_monitor;
+  gchar **rules_dirs;
+  GFileMonitor **dir_monitors; /* NULL-terminated array of GFileMonitor instances */
 
   JSRuntime *rt;
   JSContext *cx;
@@ -79,7 +79,7 @@ static void on_dir_monitor_changed (GFileMonitor     *monitor,
 enum
 {
   PROP_0,
-  PROP_RULES_DIR,
+  PROP_RULES_DIRS,
 };
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -174,40 +174,76 @@ polkit_backend_js_authority_init (PolkitBackendJsAuthority *authority)
                                                  PolkitBackendJsAuthorityPrivate);
 }
 
+static gint
+rules_file_name_cmp (const gchar *a,
+                     const gchar *b)
+{
+  gint ret;
+  const gchar *a_base;
+  const gchar *b_base;
+
+  a_base = strrchr (a, '/');
+  b_base = strrchr (b, '/');
+
+  g_assert (a_base != NULL);
+  g_assert (b_base != NULL);
+  a_base += 1;
+  b_base += 1;
+
+  ret = g_strcmp0 (a_base, b_base);
+  if (ret == 0)
+    {
+      /* /etc wins over /usr */
+      ret = g_strcmp0 (a, b);
+      g_assert (ret != 0);
+    }
+
+  return ret;
+}
+
 static void
 load_scripts (PolkitBackendJsAuthority  *authority)
 {
-  GDir *dir = NULL;
   GList *files = NULL;
   GList *l;
-  const gchar *name;
   guint num_scripts = 0;
   GError *error = NULL;
+  guint n;
 
-  polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                "Loading scripts from directory %s",
-                                authority->priv->rules_dir);
+  files = NULL;
 
-  dir = g_dir_open (authority->priv->rules_dir,
-                    0,
-                    &error);
-  if (dir == NULL)
+  for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
     {
+      const gchar *dir_name = authority->priv->rules_dirs[n];
+      GDir *dir = NULL;
+
       polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
-                                    "Error opening rules directory: %s (%s, %d)",
-                                    error->message, g_quark_to_string (error->domain), error->code);
-      g_clear_error (&error);
-      goto out;
-    }
+                                    "Loading scripts from directory %s",
+                                    dir_name);
 
-  files = NULL;
-  while ((name = g_dir_read_name (dir)) != NULL)
-    {
-      if (g_str_has_suffix (name, ".rules"))
-        files = g_list_prepend (files, g_strdup_printf ("%s/%s", authority->priv->rules_dir, name));
+      dir = g_dir_open (dir_name,
+                        0,
+                        &error);
+      if (dir == NULL)
+        {
+          polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
+                                        "Error opening rules directory: %s (%s, %d)",
+                                        error->message, g_quark_to_string (error->domain), error->code);
+          g_clear_error (&error);
+        }
+      else
+        {
+          const gchar *name;
+          while ((name = g_dir_read_name (dir)) != NULL)
+            {
+              if (g_str_has_suffix (name, ".rules"))
+                files = g_list_prepend (files, g_strdup_printf ("%s/%s", dir_name, name));
+            }
+          g_dir_close (dir);
+        }
     }
 
-  files = g_list_sort (files, (GCompareFunc) g_strcmp0);
+  files = g_list_sort (files, (GCompareFunc) rules_file_name_cmp);
 
   for (l = files; l != NULL; l = l->next)
     {
@@ -246,11 +282,7 @@ load_scripts (PolkitBackendJsAuthority  *authority)
   polkit_backend_authority_log (POLKIT_BACKEND_AUTHORITY (authority),
                                 "Finished loading, compiling and executing %d scripts",
                                 num_scripts);
-
- out:
   g_list_free_full (files, g_free);
-  if (dir != NULL)
-    g_dir_close (dir);
 }
 
 static void
@@ -318,6 +350,46 @@ on_dir_monitor_changed (GFileMonitor     *monitor,
     }
 }
 
+
+static void
+setup_file_monitors (PolkitBackendJsAuthority *authority)
+{
+  guint n;
+  GPtrArray *p;
+
+  p = g_ptr_array_new ();
+  for (n = 0; authority->priv->rules_dirs != NULL && authority->priv->rules_dirs[n] != NULL; n++)
+    {
+      GFile *file;
+      GError *error;
+      GFileMonitor *monitor;
+
+      file = g_file_new_for_path (authority->priv->rules_dirs[n]);
+      error = NULL;
+      monitor = g_file_monitor_directory (file,
+                                          G_FILE_MONITOR_NONE,
+                                          NULL,
+                                          &error);
+      if (monitor == NULL)
+        {
+          g_warning ("Error monitoring directory %s: %s",
+                     authority->priv->rules_dirs[n],
+                     error->message);
+          g_clear_error (&error);
+        }
+      else
+        {
+          g_signal_connect (monitor,
+                            "changed",
+                            G_CALLBACK (on_dir_monitor_changed),
+                            authority);
+          g_ptr_array_add (p, monitor);
+        }
+    }
+  g_ptr_array_add (p, NULL);
+  authority->priv->dir_monitors = (GFileMonitor**) g_ptr_array_free (p, FALSE);
+}
+
 static void
 polkit_backend_js_authority_constructed (GObject *object)
 {
@@ -372,6 +444,14 @@ polkit_backend_js_authority_constructed (GObject *object)
       goto fail;
     }
 
+  if (authority->priv->rules_dirs == NULL)
+    {
+      authority->priv->rules_dirs = g_new0 (gchar *, 3);
+      authority->priv->rules_dirs[0] = g_strdup (PACKAGE_SYSCONF_DIR "/polkit-1/rules.d");
+      authority->priv->rules_dirs[1] = g_strdup (PACKAGE_DATA_DIR "/polkit-1/rules.d");
+    }
+
+  setup_file_monitors (authority);
   load_scripts (authority);
 
   G_OBJECT_CLASS (polkit_backend_js_authority_parent_class)->constructed (object);
@@ -386,15 +466,18 @@ static void
 polkit_backend_js_authority_finalize (GObject *object)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
+  guint n;
 
-  g_free (authority->priv->rules_dir);
-  if (authority->priv->dir_monitor != NULL)
+  for (n = 0; authority->priv->dir_monitors != NULL && authority->priv->dir_monitors[n] != NULL; n++)
     {
-      g_signal_handlers_disconnect_by_func (authority->priv->dir_monitor,
+      GFileMonitor *monitor = authority->priv->dir_monitors[n];
+      g_signal_handlers_disconnect_by_func (monitor,
                                             G_CALLBACK (on_dir_monitor_changed),
                                             authority);
-      g_object_unref (authority->priv->dir_monitor);
+      g_object_unref (monitor);
     }
+  g_free (authority->priv->dir_monitors);
+  g_strfreev (authority->priv->rules_dirs);
 
   JS_DestroyContext (authority->priv->cx);
   JS_DestroyRuntime (authority->priv->rt);
@@ -410,35 +493,12 @@ polkit_backend_js_authority_set_property (GObject      *object,
                                           GParamSpec   *pspec)
 {
   PolkitBackendJsAuthority *authority = POLKIT_BACKEND_JS_AUTHORITY (object);
-  GFile *file;
-  GError *error;
 
   switch (property_id)
     {
-      case PROP_RULES_DIR:
-        g_assert (authority->priv->rules_dir == NULL);
-        authority->priv->rules_dir = g_value_dup_string (value);
-
-        file = g_file_new_for_path (authority->priv->rules_dir);
-        error = NULL;
-        authority->priv->dir_monitor = g_file_monitor_directory (file,
-                                                                 G_FILE_MONITOR_NONE,
-                                                                 NULL,
-                                                                 &error);
-        if (authority->priv->dir_monitor == NULL)
-          {
-            g_warning ("Error monitoring directory %s: %s",
-                       authority->priv->rules_dir,
-                       error->message);
-            g_clear_error (&error);
-          }
-        else
-          {
-            g_signal_connect (authority->priv->dir_monitor,
-                              "changed",
-                              G_CALLBACK (on_dir_monitor_changed),
-                              authority);
-          }
+      case PROP_RULES_DIRS:
+        g_assert (authority->priv->rules_dirs == NULL);
+        authority->priv->rules_dirs = (gchar **) g_value_dup_boxed (value);
         break;
 
       default:
@@ -488,12 +548,12 @@ polkit_backend_js_authority_class_init (PolkitBackendJsAuthorityClass *klass)
   interactive_authority_class->check_authorization_sync = polkit_backend_js_authority_check_authorization_sync;
 
   g_object_class_install_property (gobject_class,
-                                   PROP_RULES_DIR,
-                                   g_param_spec_string ("rules-dir",
-                                                        NULL,
-                                                        NULL,
-                                                        PACKAGE_SYSCONF_DIR "/polkit-1/rules.d",
-                                                        G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
+                                   PROP_RULES_DIRS,
+                                   g_param_spec_boxed ("rules-dirs",
+                                                       NULL,
+                                                       NULL,
+                                                       G_TYPE_STRV,
+                                                       G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE));
 
 
   g_type_class_add_private (klass, sizeof (PolkitBackendJsAuthorityPrivate));
diff --git a/test/data/etc/polkit-1/rules.d/10-testing.rules b/test/data/etc/polkit-1/rules.d/10-testing.rules
index 9453c44..d4bb324 100644
--- a/test/data/etc/polkit-1/rules.d/10-testing.rules
+++ b/test/data/etc/polkit-1/rules.d/10-testing.rules
@@ -2,6 +2,8 @@
 
 /* see test/polkitbackend/test-polkitbackendjsauthority.c */
 
+/* NOTE: this is the /etc/polkit-1/rules.d version of 10-testing.rules */
+
 polkit.addAdministratorRule(function(action, subject, details) {
     return ["unix-group:admin", "unix-user:root"];
 });
diff --git a/test/data/usr/share/polkit-1/rules.d/10-testing.rules b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
new file mode 100644
index 0000000..ab2fd97
--- /dev/null
+++ b/test/data/usr/share/polkit-1/rules.d/10-testing.rules
@@ -0,0 +1,5 @@
+/* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- */
+
+/* see test/polkitbackend/test-polkitbackendjsauthority.c */
+
+/* NOTE: this is the /usr/share/polkit-1/rules.d version of 10-testing.rules */
diff --git a/test/polkitbackend/test-polkitbackendjsauthority.c b/test/polkitbackend/test-polkitbackendjsauthority.c
index bc1b242..67f5d8b 100644
--- a/test/polkitbackend/test-polkitbackendjsauthority.c
+++ b/test/polkitbackend/test-polkitbackendjsauthority.c
@@ -36,16 +36,20 @@ static PolkitBackendJsAuthority *get_authority (void);
 static PolkitBackendJsAuthority *
 get_authority (void)
 {
-  gchar *rules_dir;
+  gchar *rules_dirs[3] = {0};
   PolkitBackendJsAuthority *authority;
 
-  rules_dir = polkit_test_get_data_path ("etc/polkit-1/rules.d");
-  g_assert (rules_dir != NULL);
+  rules_dirs[0] = polkit_test_get_data_path ("etc/polkit-1/rules.d");
+  rules_dirs[1] = polkit_test_get_data_path ("usr/share/polkit-1/rules.d");
+  rules_dirs[2] = NULL;
+  g_assert (rules_dirs[0] != NULL);
+  g_assert (rules_dirs[1] != NULL);
 
   authority = g_object_new (POLKIT_BACKEND_TYPE_JS_AUTHORITY,
-                            "rules-dir", rules_dir,
+                            "rules-dirs", rules_dirs,
                             NULL);
-  g_free (rules_dir);
+  g_free (rules_dirs[0]);
+  g_free (rules_dirs[1]);
   return authority;
 }
 


More information about the hal-commit mailing list