diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2020-10-24 15:40:57 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2020-11-13 08:57:06 +0000 |
commit | 71f5c975430b0455e7ca81b2d2d1bef0174d0be2 (patch) | |
tree | 1992d85df2913b7f624ab58b9fc8aa3d04cf0f4f /src | |
parent | 950abbf8ee8624827d63a0d0186beac81232e8f6 (diff) |
base-manager: automatic required subsystem detection
Instead of assuming we require a fixed set of subsystems to monitor,
compile the full list based on what the plugins have requested
themselves.
Diffstat (limited to 'src')
-rw-r--r-- | src/mm-base-manager.c | 62 | ||||
-rw-r--r-- | src/mm-plugin-manager.c | 98 | ||||
-rw-r--r-- | src/mm-plugin-manager.h | 1 | ||||
-rw-r--r-- | src/mm-plugin.c | 6 | ||||
-rw-r--r-- | src/mm-plugin.h | 1 |
5 files changed, 103 insertions, 65 deletions
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c index 87eddc34..27e7404b 100644 --- a/src/mm-base-manager.c +++ b/src/mm-base-manager.c @@ -368,6 +368,11 @@ handle_kernel_event (MMBaseManager *self, return FALSE; } + if (!g_strv_contains (mm_plugin_manager_get_subsystems (self->priv->plugin_manager), subsystem)) { + g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, "Invalid 'subsystem' parameter given: '%s'", subsystem); + return FALSE; + } + name = mm_kernel_event_properties_get_name (properties); if (!name) { g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS, "Missing mandatory parameter 'name'"); @@ -457,28 +462,19 @@ static void process_scan (MMBaseManager *self, gboolean manual_scan) { - GList *devices, *iter; - - devices = g_udev_client_query_by_subsystem (self->priv->udev, "tty"); - for (iter = devices; iter; iter = g_list_next (iter)) { - start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan); - g_object_unref (G_OBJECT (iter->data)); + const gchar **subsystems; + guint i; + + subsystems = mm_plugin_manager_get_subsystems (self->priv->plugin_manager); + for (i = 0; subsystems[i]; i++) { + GList *devices; + GList *iter; + + devices = g_udev_client_query_by_subsystem (self->priv->udev, subsystems[i]); + for (iter = devices; iter; iter = g_list_next (iter)) + start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan); + g_list_free_full (devices, g_object_unref); } - g_list_free (devices); - - devices = g_udev_client_query_by_subsystem (self->priv->udev, "net"); - for (iter = devices; iter; iter = g_list_next (iter)) { - start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan); - g_object_unref (G_OBJECT (iter->data)); - } - g_list_free (devices); - - devices = g_udev_client_query_by_subsystem (self->priv->udev, "usbmisc"); - for (iter = devices; iter; iter = g_list_next (iter)) { - start_device_added (self, G_UDEV_DEVICE (iter->data), manual_scan); - g_object_unref (G_OBJECT (iter->data)); - } - g_list_free (devices); } #endif @@ -1365,15 +1361,6 @@ mm_base_manager_init (MMBaseManager *self) /* Setup internal list of inhibited devices */ self->priv->inhibited_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)inhibited_device_info_free); -#if defined WITH_UDEV - { - const gchar *subsys[5] = { "tty", "net", "usbmisc", NULL }; - - /* Setup UDev client */ - self->priv->udev = g_udev_client_new (subsys); - } -#endif - /* By default, enable autoscan */ self->priv->auto_scan = TRUE; @@ -1399,12 +1386,6 @@ initable_init (GInitable *initable, { MMBaseManager *self = MM_BASE_MANAGER (initable); -#if defined WITH_UDEV - /* If autoscan enabled, list for udev events */ - if (self->priv->auto_scan) - g_signal_connect_swapped (self->priv->udev, "uevent", G_CALLBACK (handle_uevent), initable); -#endif - /* Create filter */ self->priv->filter = mm_filter_new (self->priv->filter_policy, error); if (!self->priv->filter) @@ -1415,6 +1396,15 @@ initable_init (GInitable *initable, if (!self->priv->plugin_manager) return FALSE; +#if defined WITH_UDEV + /* Create udev client based on the subsystems requested by the plugins */ + self->priv->udev = g_udev_client_new (mm_plugin_manager_get_subsystems (self->priv->plugin_manager)); + + /* If autoscan enabled, list for udev events */ + if (self->priv->auto_scan) + g_signal_connect_swapped (self->priv->udev, "uevent", G_CALLBACK (handle_uevent), initable); +#endif + /* Export the manager interface */ if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (initable), self->priv->connection, diff --git a/src/mm-plugin-manager.c b/src/mm-plugin-manager.c index e76c9a82..ed7a96ff 100644 --- a/src/mm-plugin-manager.c +++ b/src/mm-plugin-manager.c @@ -62,6 +62,9 @@ struct _MMPluginManagerPrivate { /* List of ongoing device support checks */ GList *device_contexts; + + /* Full list of subsystems requested by the registered plugins */ + gchar **subsystems; }; /*****************************************************************************/ @@ -1601,6 +1604,14 @@ mm_plugin_manager_peek_plugin (MMPluginManager *self, /*****************************************************************************/ +const gchar ** +mm_plugin_manager_get_subsystems (MMPluginManager *self) +{ + return (const gchar **) self->priv->subsystems; +} + +/*****************************************************************************/ + static void register_plugin_whitelist_tags (MMPluginManager *self, MMPlugin *plugin) @@ -1765,15 +1776,17 @@ out: } static gboolean -load_plugins (MMPluginManager *self, - GError **error) +load_plugins (MMPluginManager *self, + GError **error) { - GDir *dir = NULL; - const gchar *fname; - gchar *plugindir_display = NULL; - GList *shared_paths = NULL; - GList *plugin_paths = NULL; - GList *l; + GDir *dir = NULL; + const gchar *fname; + GList *shared_paths = NULL; + GList *plugin_paths = NULL; + GList *l; + GPtrArray *subsystems = NULL; + g_autofree gchar *subsystems_str = NULL; + g_autofree gchar *plugindir_display = NULL; if (!g_module_supported ()) { g_set_error (error, @@ -1811,21 +1824,41 @@ load_plugins (MMPluginManager *self, load_shared (self, (const gchar *)(l->data)); /* Load all plugins */ + subsystems = g_ptr_array_new (); for (l = plugin_paths; l; l = g_list_next (l)) { - MMPlugin *plugin; + MMPlugin *plugin; + const gchar **plugin_subsystems; + guint i; plugin = load_plugin (self, (const gchar *)(l->data)); if (!plugin) continue; + /* Ignore plugins that don't specify subsystems */ + plugin_subsystems = mm_plugin_get_allowed_subsystems (plugin); + if (!plugin_subsystems) { + mm_obj_warn (self, "plugin '%s' doesn't specify allowed subsystems: ignored", + mm_plugin_get_name (plugin)); + continue; + } + + /* Process generic plugin */ if (mm_plugin_is_generic (plugin)) { - if (self->priv->generic) - mm_obj_warn (self, "cannot register more than one generic plugin"); - else - self->priv->generic = plugin; + if (self->priv->generic) { + mm_obj_warn (self, "plugin '%s' is generic and another one is already registered: ignored", + mm_plugin_get_name (plugin)); + continue; + } + self->priv->generic = plugin; } else self->priv->plugins = g_list_append (self->priv->plugins, plugin); + /* Track required subsystems, avoiding duplicates in the list */ + for (i = 0; plugin_subsystems[i]; i++) { + if (!g_ptr_array_find_with_equal_func (subsystems, plugin_subsystems[i], g_str_equal, NULL)) + g_ptr_array_add (subsystems, g_strdup (plugin_subsystems[i])); + } + /* Register plugin whitelist rules in filter, if any */ register_plugin_whitelist_tags (self, plugin); register_plugin_whitelist_vendor_ids (self, plugin); @@ -1846,15 +1879,28 @@ load_plugins (MMPluginManager *self, goto out; } - mm_obj_dbg (self, "successfully loaded %u plugins", - g_list_length (self->priv->plugins) + !!self->priv->generic); + /* Validate required subsystems */ + if (!subsystems->len) { + g_set_error (error, + MM_CORE_ERROR, + MM_CORE_ERROR_NO_PLUGINS, + "empty list of subsystems required by plugins"); + goto out; + } + /* Add trailing NULL and store as GStrv */ + g_ptr_array_add (subsystems, NULL); + self->priv->subsystems = (gchar **) g_ptr_array_free (subsystems, FALSE); + subsystems_str = g_strjoinv (", ", self->priv->subsystems); + + mm_obj_dbg (self, "successfully loaded %u plugins registering %u subsystems: %s", + g_list_length (self->priv->plugins) + !!self->priv->generic, + g_strv_length (self->priv->subsystems), subsystems_str); out: g_list_free_full (shared_paths, g_free); g_list_free_full (plugin_paths, g_free); if (dir) g_dir_close (dir); - g_free (plugindir_display); /* Return TRUE if at least one plugin found */ return (self->priv->plugins || self->priv->generic); @@ -1884,12 +1930,12 @@ mm_plugin_manager_new (const gchar *plugin_dir, } static void -mm_plugin_manager_init (MMPluginManager *manager) +mm_plugin_manager_init (MMPluginManager *self) { /* Initialize opaque pointer to private data */ - manager->priv = G_TYPE_INSTANCE_GET_PRIVATE (manager, - MM_TYPE_PLUGIN_MANAGER, - MMPluginManagerPrivate); + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + MM_TYPE_PLUGIN_MANAGER, + MMPluginManagerPrivate); } static void @@ -1949,17 +1995,11 @@ dispose (GObject *object) { MMPluginManager *self = MM_PLUGIN_MANAGER (object); - /* Cleanup list of plugins */ - if (self->priv->plugins) { - g_list_free_full (self->priv->plugins, g_object_unref); - self->priv->plugins = NULL; - } + g_list_free_full (g_steal_pointer (&self->priv->plugins), g_object_unref); g_clear_object (&self->priv->generic); - - g_free (self->priv->plugin_dir); - self->priv->plugin_dir = NULL; - + g_clear_pointer (&self->priv->plugin_dir, g_free); g_clear_object (&self->priv->filter); + g_clear_pointer (&self->priv->subsystems, g_strfreev); G_OBJECT_CLASS (mm_plugin_manager_parent_class)->dispose (object); } diff --git a/src/mm-plugin-manager.h b/src/mm-plugin-manager.h index 079fc54b..79e7c1a1 100644 --- a/src/mm-plugin-manager.h +++ b/src/mm-plugin-manager.h @@ -65,5 +65,6 @@ MMPlugin * mm_plugin_manager_device_support_check_finish (MMPluginManager GError **error); MMPlugin *mm_plugin_manager_peek_plugin (MMPluginManager *self, const gchar *plugin_name); +const gchar **mm_plugin_manager_get_subsystems (MMPluginManager *self); #endif /* MM_PLUGIN_MANAGER_H */ diff --git a/src/mm-plugin.c b/src/mm-plugin.c index a713ddf1..47855d9d 100644 --- a/src/mm-plugin.c +++ b/src/mm-plugin.c @@ -147,6 +147,12 @@ mm_plugin_get_name (MMPlugin *self) } const gchar ** +mm_plugin_get_allowed_subsystems (MMPlugin *self) +{ + return (const gchar **) self->priv->subsystems; +} + +const gchar ** mm_plugin_get_allowed_udev_tags (MMPlugin *self) { return (const gchar **) self->priv->udev_tags; diff --git a/src/mm-plugin.h b/src/mm-plugin.h index 7011f9c4..b27e7a2f 100644 --- a/src/mm-plugin.h +++ b/src/mm-plugin.h @@ -126,6 +126,7 @@ GType mm_plugin_get_type (void); G_DEFINE_AUTOPTR_CLEANUP_FUNC (MMPlugin, g_object_unref) const gchar *mm_plugin_get_name (MMPlugin *self); +const gchar **mm_plugin_get_allowed_subsystems (MMPlugin *self); const gchar **mm_plugin_get_allowed_udev_tags (MMPlugin *self); const guint16 *mm_plugin_get_allowed_vendor_ids (MMPlugin *self); const mm_uint16_pair *mm_plugin_get_allowed_product_ids (MMPlugin *self); |