From 89865529ec98067ba8eada3b59938204534de7b2 Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 21 May 2012 10:45:08 -0400 Subject: Also load rules from /usr/share/polkit/rules.d ... in addition to /etc/polkit/rules.d. Signed-off-by: David Zeuthen --- src/polkitbackend/polkitbackendjsauthority.c | 186 ++++++++++++++------- test/data/etc/polkit-1/rules.d/10-testing.rules | 2 + .../usr/share/polkit-1/rules.d/10-testing.rules | 5 + test/polkitbackend/test-polkitbackendjsauthority.c | 14 +- 4 files changed, 139 insertions(+), 68 deletions(-) create mode 100644 test/data/usr/share/polkit-1/rules.d/10-testing.rules 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; } -- cgit v1.2.1