libnm: add nm_vpn_editor_plugin_load_from_file() function

This commit is contained in:
Thomas Haller 2015-05-28 22:16:00 +02:00
parent b5cc017ba4
commit eed0d0c58f
4 changed files with 159 additions and 0 deletions

View file

@ -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:
*

View file

@ -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__ */

View file

@ -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;

View file

@ -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