diff options
author | Thomas Haller <thaller@redhat.com> | 2015-05-28 22:16:00 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2015-07-29 22:34:35 +0200 |
commit | eed0d0c58f7f13638eb587e240737048d729cb68 (patch) | |
tree | 4a0a0bc21f38f92030b80737f7434fd56230d78c | |
parent | b5cc017ba473de011881e40b26b3ee3433f1567c (diff) | |
download | NetworkManager-eed0d0c58f7f13638eb587e240737048d729cb68.tar.gz |
libnm: add nm_vpn_editor_plugin_load_from_file() function
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.c | 147 | ||||
-rw-r--r-- | libnm-core/nm-vpn-editor-plugin.h | 10 | ||||
-rw-r--r-- | libnm/libnm.ver | 1 | ||||
-rw-r--r-- | po/POTFILES.in | 1 |
4 files changed, 159 insertions, 0 deletions
diff --git a/libnm-core/nm-vpn-editor-plugin.c b/libnm-core/nm-vpn-editor-plugin.c index b36b736859..d5fa6d819b 100644 --- a/libnm-core/nm-vpn-editor-plugin.c +++ b/libnm-core/nm-vpn-editor-plugin.c @@ -24,6 +24,13 @@ #include "nm-vpn-editor-plugin.h" +#include <gio/gio.h> +#include <glib/gi18n-lib.h> + +#include "nm-macros-internal.h" +#include "gsystem-local-alloc.h" +#include "nm-core-internal.h" + static void nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface); G_DEFINE_INTERFACE (NMVpnEditorPlugin, nm_vpn_editor_plugin, G_TYPE_OBJECT) @@ -67,6 +74,146 @@ nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface) G_PARAM_STATIC_STRINGS)); } +/*********************************************************************/ + +/** + * nm_vpn_editor_plugin_load_from_file: + * @plugin_filename: The path to the share library to load. + * Apply some common heuristics to find the library, such as + * appending "so" file ending. + * If the path is not an absolute path or no matching module + * can be found, lookup inside a directory defined at compile time. + * Due to this, @check_file might be called for two different paths. + * @check_name: if not-null, check that the loaded plugin has + * the given name. + * @check_service: if not-null, check that the loaded plugin advertises + * the given service. + * @check_owner: if non-negative, check whether the file is owned + * by UID @check_owner or by root. In this case also check that + * the file is not writable by anybody else. + * @check_file: optional callback to validate the file prior to + * loading the shared library. + * @user_data: user data for @check_file + * @error: on failure the error reason. + * + * Load the shared libary @plugin_filename and create a new + * #NMVpnEditorPlugin instace via the #NMVpnEditorPluginFactory + * function. + * + * Returns: (transfer-full): a new plugin instance or %NULL on error. + * + * Since: 1.2 + */ +NMVpnEditorPlugin * +nm_vpn_editor_plugin_load_from_file (const char *plugin_filename, + const char *check_name, + const char *check_service, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError **error) +{ + GModule *module = NULL; + gs_free_error GError *local = NULL; + NMVpnEditorPluginFactory factory = NULL; + NMVpnEditorPlugin *editor_plugin = NULL; + + g_return_val_if_fail (plugin_filename && *plugin_filename, NULL); + + if (g_path_is_absolute (plugin_filename)) { + gs_free char *module_filename = NULL; + + module_filename = _nm_utils_check_module_file (plugin_filename, + check_owner, + check_file, + user_data, + &local); + if (module_filename) + module = g_module_open (module_filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + } + + if (!module) { + if (local) { + g_propagate_error (error, local); + local = NULL; + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load plugin %s"), plugin_filename); + } + return NULL; + } + g_clear_error (&local); + + if (g_module_symbol (module, "nm_vpn_editor_plugin_factory", (gpointer) &factory)) { + gs_free_error GError *factory_error = NULL; + gboolean success = FALSE; + + editor_plugin = factory (&factory_error); + + g_assert (!editor_plugin || G_IS_OBJECT (editor_plugin)); + + if (editor_plugin) { + gs_free char *plug_name = NULL, *plug_service = NULL; + + /* Validate plugin properties */ + + g_object_get (G_OBJECT (editor_plugin), + NM_VPN_EDITOR_PLUGIN_NAME, &plug_name, + NM_VPN_EDITOR_PLUGIN_SERVICE, &plug_service, + NULL); + + if (check_name && g_strcmp0 (plug_name, check_name) != 0) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load VPN plugin in '%s': invalid plugin name"), + g_module_name (module)); + } else if ( check_service + && g_strcmp0 (plug_service, check_service) != 0) { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("cannot load VPN plugin in '%s': invalid service name"), + g_module_name (module)); + } else { + /* Success! */ + g_object_set_data_full (G_OBJECT (editor_plugin), "gmodule", module, + (GDestroyNotify) g_module_close); + success = TRUE; + } + } else { + if (factory_error) { + g_propagate_error (error, factory_error); + factory_error = NULL; + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("unknown error initializing plugin %s"), plugin_filename); + } + } + + if (!success) { + g_module_close (module); + editor_plugin = NULL; + } + } else { + g_set_error (error, + NM_VPN_PLUGIN_ERROR, + NM_VPN_PLUGIN_ERROR_FAILED, + _("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"), + g_module_name (module), g_module_error ()); + g_module_close (module); + editor_plugin = NULL; + } + + return editor_plugin; +} + +/*********************************************************************/ + /** * nm_vpn_editor_plugin_get_editor: * diff --git a/libnm-core/nm-vpn-editor-plugin.h b/libnm-core/nm-vpn-editor-plugin.h index a0b1f7aca2..83d765d097 100644 --- a/libnm-core/nm-vpn-editor-plugin.h +++ b/libnm-core/nm-vpn-editor-plugin.h @@ -30,6 +30,7 @@ #include <glib-object.h> #include "nm-connection.h" +#include "nm-utils.h" G_BEGIN_DECLS @@ -138,6 +139,15 @@ gboolean nm_vpn_editor_plugin_export (NMVpnEditorPlugin *pl char *nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin, NMConnection *connection); +NM_AVAILABLE_IN_1_2 +NMVpnEditorPlugin *nm_vpn_editor_plugin_load_from_file (const char *plugin_filename, + const char *check_name, + const char *check_service, + int check_owner, + NMUtilsCheckFilePredicate check_file, + gpointer user_data, + GError **error); + G_END_DECLS #endif /* __NM_VPN_EDITOR_PLUGIN_H__ */ diff --git a/libnm/libnm.ver b/libnm/libnm.ver index 885e063203..43684195e3 100644 --- a/libnm/libnm.ver +++ b/libnm/libnm.ver @@ -882,6 +882,7 @@ global: nm_utils_bond_mode_string_to_int; nm_utils_enum_from_str; nm_utils_enum_to_str; + nm_vpn_editor_plugin_load_from_file; nm_vpn_plugin_info_get_filename; nm_vpn_plugin_info_get_name; nm_vpn_plugin_info_get_plugin; diff --git a/po/POTFILES.in b/po/POTFILES.in index 4b117109e7..7b2c37ae94 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -77,6 +77,7 @@ libnm-core/nm-setting-wireless-security.c libnm-core/nm-setting-wireless.c libnm-core/nm-setting.c libnm-core/nm-utils.c +libnm-core/nm-vpn-editor-plugin.c libnm-core/nm-vpn-plugin-info.c libnm-glib/nm-device.c libnm-glib/nm-remote-connection.c |