NetworkManager/libnm-core/nm-vpn-editor-plugin.c
Thomas Haller 3b69f02164 all: unify format of our Copyright source code comments
```bash

readarray -d '' FILES < <(
  git ls-files -z \
    ':(exclude)po' \
    ':(exclude)shared/c-rbtree' \
    ':(exclude)shared/c-list' \
    ':(exclude)shared/c-siphash' \
    ':(exclude)shared/c-stdaux' \
    ':(exclude)shared/n-acd' \
    ':(exclude)shared/n-dhcp4' \
    ':(exclude)src/systemd/src' \
    ':(exclude)shared/systemd/src' \
    ':(exclude)m4' \
    ':(exclude)COPYING*'
  )

sed \
  -e 's/^\(--\|#\| \*\) *\(([cC]) *\)\?Copyright \+\(\(([cC])\) \+\)\?\(\(20\|19\)[0-9][0-9]\) *[-–] *\(\(20\|19\)[0-9][0-9]\) \+\([^ ].*\)$/\1 C1pyright#\5 - \7#\9/' \
  -e 's/^\(--\|#\| \*\) *\(([cC]) *\)\?Copyright \+\(\(([cC])\) \+\)\?\(\(20\|19\)[0-9][0-9]\) *[,] *\(\(20\|19\)[0-9][0-9]\) \+\([^ ].*\)$/\1 C2pyright#\5, \7#\9/' \
  -e 's/^\(--\|#\| \*\) *\(([cC]) *\)\?Copyright \+\(\(([cC])\) \+\)\?\(\(20\|19\)[0-9][0-9]\) \+\([^ ].*\)$/\1 C3pyright#\5#\7/' \
  -e 's/^Copyright \(\(20\|19\)[0-9][0-9]\) \+\([^ ].*\)$/C4pyright#\1#\3/' \
  -i \
  "${FILES[@]}"

echo ">>> untouched Copyright lines"
git grep Copyright "${FILES[@]}"

echo ">>> Copyright lines with unusual extra"
git grep '\<C[0-9]pyright#' "${FILES[@]}" | grep -i reserved

sed \
  -e 's/\<C[0-9]pyright#\([^#]*\)#\(.*\)$/Copyright (C) \1 \2/' \
  -i \
  "${FILES[@]}"

```

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/298
2019-10-02 17:03:52 +02:00

521 lines
17 KiB
C

// SPDX-License-Identifier: LGPL-2.1+
/*
* Copyright (C) 2008 Novell, Inc.
* Copyright (C) 2008 - 2010 Red Hat, Inc.
* Copyright (C) 2015 Red Hat, Inc.
*/
#include "nm-default.h"
#include "nm-vpn-editor-plugin.h"
#include <dlfcn.h>
#include <gmodule.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)
static void
nm_vpn_editor_plugin_default_init (NMVpnEditorPluginInterface *iface)
{
/**
* NMVpnEditorPlugin:name:
*
* Short display name of the VPN plugin.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_NAME, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnEditorPlugin:description:
*
* Longer description of the VPN plugin.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_DESCRIPTION, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
/**
* NMVpnEditorPlugin:service:
*
* D-Bus service name of the plugin's VPN service.
*/
g_object_interface_install_property (iface,
g_param_spec_string (NM_VPN_EDITOR_PLUGIN_SERVICE, "", "",
NULL,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS));
}
/*****************************************************************************/
typedef struct {
NMVpnPluginInfo *plugin_info;
} NMVpnEditorPluginPrivate;
static void
_private_destroy (gpointer data)
{
NMVpnEditorPluginPrivate *priv = data;
if (priv->plugin_info)
g_object_remove_weak_pointer ((GObject *) priv->plugin_info, (gpointer *) &priv->plugin_info);
g_slice_free (NMVpnEditorPluginPrivate, priv);
}
static NMVpnEditorPluginPrivate *
_private_get (NMVpnEditorPlugin *plugin, gboolean create)
{
static GQuark quark = 0;
NMVpnEditorPluginPrivate *priv;
nm_assert (NM_IS_VPN_EDITOR_PLUGIN (plugin));
if (G_UNLIKELY (quark == 0))
quark = g_quark_from_string ("nm-vpn-editor-plugin-private");
priv = g_object_get_qdata ((GObject *) plugin, quark);
if (G_LIKELY (priv))
return priv;
if (!create)
return NULL;
priv = g_slice_new0 (NMVpnEditorPluginPrivate);
g_object_set_qdata_full ((GObject *) plugin, quark, priv, _private_destroy);
return priv;
}
#define NM_VPN_EDITOR_PLUGIN_GET_PRIVATE(plugin) _private_get (plugin, TRUE)
#define NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE(plugin) _private_get (plugin, FALSE)
/*****************************************************************************/
/**
* nm_vpn_editor_plugin_get_plugin_info:
* @plugin: the #NMVpnEditorPlugin instance
*
* Returns: (transfer none): if set, return the #NMVpnPluginInfo instance.
*
* Since: 1.4
*/
NMVpnPluginInfo *
nm_vpn_editor_plugin_get_plugin_info (NMVpnEditorPlugin *plugin)
{
NMVpnEditorPluginPrivate *priv;
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
priv = NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE (plugin);
return priv ? priv->plugin_info : NULL;
}
/**
* nm_vpn_editor_plugin_set_plugin_info:
* @plugin: the #NMVpnEditorPlugin instance
* @plugin_info: (allow-none): a #NMVpnPluginInfo instance or %NULL
*
* Set or clear the plugin-info instance.
* This takes a weak reference on @plugin_info, to avoid circular
* reference as the plugin-info might also reference the editor-plugin.
*
* Since: 1.4
*/
void
nm_vpn_editor_plugin_set_plugin_info (NMVpnEditorPlugin *plugin, NMVpnPluginInfo *plugin_info)
{
NMVpnEditorPluginInterface *interface;
NMVpnEditorPluginPrivate *priv;
g_return_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin));
if (!plugin_info) {
priv = NM_VPN_EDITOR_PLUGIN_TRY_GET_PRIVATE (plugin);
if (!priv)
return;
} else {
g_return_if_fail (NM_IS_VPN_PLUGIN_INFO (plugin_info));
priv = NM_VPN_EDITOR_PLUGIN_GET_PRIVATE (plugin);
}
if (priv->plugin_info == plugin_info)
return;
if (priv->plugin_info)
g_object_remove_weak_pointer ((GObject *) priv->plugin_info, (gpointer *) &priv->plugin_info);
priv->plugin_info = plugin_info;
if (priv->plugin_info)
g_object_add_weak_pointer ((GObject *) priv->plugin_info, (gpointer *) &priv->plugin_info);
if (plugin_info) {
interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin);
if (interface->notify_plugin_info_set)
interface->notify_plugin_info_set (plugin, plugin_info);
}
}
/*****************************************************************************/
/**
* nm_vpn_editor_plugin_get_vt:
* @plugin: the #NMVpnEditorPlugin
* @vt: (out): buffer to be filled with the VT table of the plugin
* @vt_size: the size of the buffer. Can be 0 to only query the
* size of plugin's VT.
*
* Returns an opaque VT function table for the plugin to extend
* functionality. The actual meaning of NMVpnEditorPluginVT is not
* defined in public API of libnm, instead it must be agreed by
* both the plugin and the caller. See the header-only file
* 'nm-vpn-editor-plugin-call.h' which defines the meaning.
*
* Returns: the actual size of the @plugin's virtual function table.
*
* Since: 1.4
**/
gsize
nm_vpn_editor_plugin_get_vt (NMVpnEditorPlugin *plugin,
NMVpnEditorPluginVT *vt,
gsize vt_size)
{
const NMVpnEditorPluginVT *p_vt = NULL;
gsize p_vt_size = 0;
NMVpnEditorPluginInterface *interface;
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
if (vt_size) {
g_return_val_if_fail (vt, 0);
memset (vt, 0, vt_size);
}
interface = NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin);
if (interface->get_vt) {
p_vt = interface->get_vt (plugin, &p_vt_size);
if (!p_vt)
p_vt_size = 0;
g_return_val_if_fail (p_vt_size, 0);
memcpy (vt, p_vt, MIN (vt_size, p_vt_size));
}
return p_vt_size;
}
/*****************************************************************************/
static NMVpnEditorPlugin *
_nm_vpn_editor_plugin_load (const char *plugin_name,
gboolean do_file_checks,
const char *check_service,
int check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
GError **error)
{
void *dl_module = NULL;
gboolean loaded_before;
NMVpnEditorPluginFactory factory = NULL;
gs_unref_object NMVpnEditorPlugin *editor_plugin = NULL;
gs_free char *plugin_filename_free = NULL;
const char *plugin_filename;
gs_free_error GError *factory_error = NULL;
gs_free char *plug_name = NULL;
gs_free char *plug_service = NULL;
g_return_val_if_fail (plugin_name && *plugin_name, NULL);
/* if @do_file_checks is FALSE, we pass plugin_name directly to
* g_module_open().
*
* Otherwise, we allow for library names without path component.
* In which case, we prepend the plugin directory and form an
* absolute path. In that case, we perform checks on the file.
*
* One exception is that we don't allow for the "la" suffix. The
* reason is that g_module_open() interprets files with this extension
* special and we don't want that. */
plugin_filename = plugin_name;
if (do_file_checks) {
if ( !strchr (plugin_name, '/')
&& !g_str_has_suffix (plugin_name, ".la")) {
plugin_filename_free = g_module_build_path (NMVPNDIR, plugin_name);
plugin_filename = plugin_filename_free;
}
}
dl_module = dlopen (plugin_filename, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
if ( !dl_module
&& do_file_checks) {
/* If the module is already loaded, we skip the file checks.
*
* _nm_utils_check_module_file() fails with ENOENT if the plugin file
* does not exist. That is relevant, because nm-applet checks for that. */
if (!_nm_utils_check_module_file (plugin_filename,
check_owner,
check_file,
user_data,
error))
return NULL;
}
if (dl_module) {
loaded_before = TRUE;
} else {
loaded_before = FALSE;
dl_module = dlopen (plugin_filename, RTLD_LAZY | RTLD_LOCAL);
}
if (!dl_module) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("cannot load plugin \"%s\": %s"),
plugin_name,
dlerror () ?: "unknown reason");
return NULL;
}
factory = dlsym (dl_module, "nm_vpn_editor_plugin_factory");
if (!factory) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("failed to load nm_vpn_editor_plugin_factory() from %s (%s)"),
plugin_name, dlerror ());
dlclose (dl_module);
return NULL;
}
editor_plugin = factory (&factory_error);
if (loaded_before) {
/* we want to leak the library, because the factory will register glib
* types, which cannot be unregistered.
*
* However, if the library was already loaded before, we want to return
* our part of the reference count. */
dlclose (dl_module);
}
if (!editor_plugin) {
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_name);
}
return NULL;
}
g_return_val_if_fail (G_IS_OBJECT (editor_plugin), 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 (!plug_name || !*plug_name) {
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("cannot load VPN plugin in '%s': missing plugin name"),
plugin_name);
return NULL;
}
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"),
plugin_name);
return NULL;
}
return g_steal_pointer (&editor_plugin);
}
/**
* nm_vpn_editor_plugin_load_from_file:
* @plugin_name: The path or name of the shared library to load.
* The path must either be an absolute filename to an existing file.
* Alternatively, it can be the name (without path) of a library in the
* plugin directory of NetworkManager.
* @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: (scope call): 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 library @plugin_name and create a new
* #NMVpnEditorPlugin instance via the #NMVpnEditorPluginFactory
* function.
*
* If @plugin_name is not an absolute path name, it assumes the file
* is in the plugin directory of NetworkManager. In any case, the call
* will do certain checks on the file before passing it to dlopen.
* A consequence for that is, that you cannot omit the ".so" suffix
* as you could for nm_vpn_editor_plugin_load().
*
* 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_name,
const char *check_service,
int check_owner,
NMUtilsCheckFilePredicate check_file,
gpointer user_data,
GError **error)
{
return _nm_vpn_editor_plugin_load (plugin_name,
TRUE,
check_service,
check_owner,
check_file,
user_data,
error);
}
/**
* nm_vpn_editor_plugin_load:
* @plugin_name: The name of the shared library to load.
* This path will be directly passed to dlopen() without
* further checks.
* @check_service: if not-null, check that the loaded plugin advertises
* the given service.
* @error: on failure the error reason.
*
* Load the shared library @plugin_name and create a new
* #NMVpnEditorPlugin instance via the #NMVpnEditorPluginFactory
* function.
*
* This is similar to nm_vpn_editor_plugin_load_from_file(), but
* it does no validation of the plugin name, instead passes it directly
* to dlopen(). If you have the full path to a plugin file,
* nm_vpn_editor_plugin_load_from_file() is preferred.
*
* Returns: (transfer full): a new plugin instance or %NULL on error.
*
* Since: 1.4
*/
NMVpnEditorPlugin *
nm_vpn_editor_plugin_load (const char *plugin_name,
const char *check_service,
GError **error)
{
return _nm_vpn_editor_plugin_load (plugin_name,
FALSE,
check_service,
-1,
NULL,
NULL,
error);
}
/*****************************************************************************/
/**
* nm_vpn_editor_plugin_get_editor:
* @plugin: the #NMVpnEditorPlugin
* @connection: the #NMConnection to be edited
* @error: on return, an error or %NULL
*
* Returns: (transfer full): a new #NMVpnEditor or %NULL on error
*/
NMVpnEditor *
nm_vpn_editor_plugin_get_editor (NMVpnEditorPlugin *plugin,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_editor (plugin, connection, error);
}
NMVpnEditorPluginCapability
nm_vpn_editor_plugin_get_capabilities (NMVpnEditorPlugin *plugin)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), 0);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_capabilities (plugin);
}
/**
* nm_vpn_editor_plugin_import:
* @plugin: the #NMVpnEditorPlugin
* @path: full path to the file to attempt to read into a new #NMConnection
* @error: on return, an error or %NULL
*
* Returns: (transfer full): a new #NMConnection imported from @path, or %NULL
* on error or if the file at @path was not recognized by this plugin
*/
NMConnection *
nm_vpn_editor_plugin_import (NMVpnEditorPlugin *plugin,
const char *path,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_IMPORT) {
g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file != NULL, NULL);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->import_from_file (plugin, path, error);
}
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("the plugin does not support import capability"));
return NULL;
}
gboolean
nm_vpn_editor_plugin_export (NMVpnEditorPlugin *plugin,
const char *path,
NMConnection *connection,
GError **error)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), FALSE);
if (nm_vpn_editor_plugin_get_capabilities (plugin) & NM_VPN_EDITOR_PLUGIN_CAPABILITY_EXPORT) {
g_return_val_if_fail (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file != NULL, FALSE);
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->export_to_file (plugin, path, connection, error);
}
g_set_error (error,
NM_VPN_PLUGIN_ERROR,
NM_VPN_PLUGIN_ERROR_FAILED,
_("the plugin does not support export capability"));
return FALSE;
}
char *
nm_vpn_editor_plugin_get_suggested_filename (NMVpnEditorPlugin *plugin,
NMConnection *connection)
{
g_return_val_if_fail (NM_IS_VPN_EDITOR_PLUGIN (plugin), NULL);
if (NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename)
return NM_VPN_EDITOR_PLUGIN_GET_INTERFACE (plugin)->get_suggested_filename (plugin, connection);
return NULL;
}