diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2025-01-12 14:23:01 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2025-01-12 14:23:01 (GMT) |
commit | baa854bfcc969022a00617b58a661e37f345cab5 (patch) | |
tree | 093d3ace4c2e1ad8fa37ce5e08723f768fffbada /src | |
parent | 0fdba5bd3e2c9ed913619990dbda7925867e46c5 (diff) |
Rewrite the plugin system.
Diffstat (limited to 'src')
-rw-r--r-- | src/common/compiler.h | 16 | ||||
-rw-r--r-- | src/common/cpp.h | 8 | ||||
-rw-r--r-- | src/plugins/Makefile.am | 16 | ||||
-rw-r--r-- | src/plugins/dt.c | 2 | ||||
-rw-r--r-- | src/plugins/manager-int.h | 54 | ||||
-rw-r--r-- | src/plugins/manager.c | 113 | ||||
-rw-r--r-- | src/plugins/manager.h | 61 | ||||
-rw-r--r-- | src/plugins/native-int.h | 62 | ||||
-rw-r--r-- | src/plugins/native.c | 278 | ||||
-rw-r--r-- | src/plugins/native.h | 39 | ||||
-rw-r--r-- | src/plugins/pglist.c | 355 | ||||
-rw-r--r-- | src/plugins/pglist.h | 63 | ||||
-rw-r--r-- | src/plugins/plugin-def.h | 16 | ||||
-rw-r--r-- | src/plugins/plugin-int.h | 88 | ||||
-rw-r--r-- | src/plugins/plugin.c | 970 | ||||
-rw-r--r-- | src/plugins/plugin.h | 41 | ||||
-rw-r--r-- | src/plugins/self.h | 99 |
17 files changed, 1235 insertions, 1046 deletions
diff --git a/src/common/compiler.h b/src/common/compiler.h index 2585e47..65df8a4 100644 --- a/src/common/compiler.h +++ b/src/common/compiler.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * compiler.h - prototypes pour le regroupement d'astuces à destination du compilateur * - * Copyright (C) 2024 Cyrille Bagard + * Copyright (C) 2024-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -34,5 +34,19 @@ #define __weak __attribute__((weak)) +/** + * Contournement des avertissements de la forme suivante : + * + * assignment to 'const char * const*' from incompatible pointer type 'char **' [-Wincompatible-pointer-types] + * + * Références : + * - https://www.reddit.com/r/C_Programming/comments/qa2231/const_char_const_and_char_are_incompatible/ + * - https://stackoverflow.com/questions/78125/why-cant-i-convert-char-to-a-const-char-const-in-c + * - https://c-faq.com/ansi/constmismatch.html + */ + +#define CONST_ARRAY_CAST(a, tp) (const tp **)a + + #endif /* _COMMON_COMPILER_H */ diff --git a/src/common/cpp.h b/src/common/cpp.h index 39e7676..2644281 100644 --- a/src/common/cpp.h +++ b/src/common/cpp.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * cpp.h - prototypes pour avoir à disposition un langage C plus plus mieux * - * Copyright (C) 2010-2020 Cyrille Bagard + * Copyright (C) 2010-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -31,6 +31,12 @@ /** + * Fournit la taille d'une chaîne statique. + */ +#define STATIC_STR_SIZE(s) (sizeof(s) - 1) + + +/** * Fournit la taille d'un tableau statique. */ #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index dd191fa..555c449 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -1,12 +1,16 @@ noinst_LTLIBRARIES = libplugins.la -libplugins_la_SOURCES = \ - dt.h dt.c \ - pglist.h pglist.c \ - plugin-def.h \ - plugin-int.h \ - plugin.h plugin.c \ +libplugins_la_SOURCES = \ + dt.h dt.c \ + manager-int.h \ + manager.h manager.c \ + native-int.h \ + native.h native.c \ + pglist.h pglist.c \ + plugin-def.h \ + plugin-int.h \ + plugin.h plugin.c \ self.h libplugins_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBXML_CFLAGS) diff --git a/src/plugins/dt.c b/src/plugins/dt.c index 2899845..9de0553 100644 --- a/src/plugins/dt.c +++ b/src/plugins/dt.c @@ -550,7 +550,7 @@ gpointer create_object_from_type(GType type) result = NULL; if (g_dynamic_types_find(_chrysalide_dtypes, type) != NULL) - result = build_type_instance(type); + result = NULL;//build_type_instance(type); else result = g_object_new(type, NULL); diff --git a/src/plugins/manager-int.h b/src/plugins/manager-int.h new file mode 100644 index 0000000..5ccc8f8 --- /dev/null +++ b/src/plugins/manager-int.h @@ -0,0 +1,54 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * singleton-int.h - définitions internes propres aux interventions dans la gestion des extensions + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_CONTAINER_INT_H +#define _PLUGINS_CONTAINER_INT_H + + +#include "manager.h" + + + +/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */ + + +/* Accompagne la fin du chargement des modules natifs. */ +typedef void (* handle_native_plugins_cb) (GPluginManager *); + +/* Prend acte du chargement de l'ensemble des greffons. */ +typedef void (* handle_all_plugins_cb) (GPluginManager *); + + +/* Instance d'objet visant à être unique (interface) */ +struct _GPluginManagerInterface +{ + GTypeInterface base_iface; /* A laisser en premier */ + + handle_native_plugins_cb handle_native; /* Greffons natifs chargés */ + handle_all_plugins_cb handle_all; /* Ensemble des greffons chargé*/ + +}; + + + +#endif /* _PLUGINS_CONTAINER_INT_H */ diff --git a/src/plugins/manager.c b/src/plugins/manager.c new file mode 100644 index 0000000..381fbc1 --- /dev/null +++ b/src/plugins/manager.c @@ -0,0 +1,113 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.c - intervention dans la gestion des extensions + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "manager.h" + + +#include "manager-int.h" + + + +/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */ + + +/* Procède à l'initialisation de l'interface de gestion. */ +static void g_plugin_manager_default_init(GPluginManagerInterface *); + + + +/* ---------------------------------------------------------------------------------- */ +/* INTERVENTION DANS LA GESTION DE GREFFONS */ +/* ---------------------------------------------------------------------------------- */ + + +/* Détermine le type d'une interface pour l'intervention dans la gestion des greffons. */ +G_DEFINE_INTERFACE(GPluginManager, g_plugin_manager, G_TYPE_OBJECT) + + +/****************************************************************************** +* * +* Paramètres : iface = interface GLib à initialiser. * +* * +* Description : Procède à l'initialisation de l'interface de gestion. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_plugin_manager_default_init(GPluginManagerInterface *iface) +{ + iface->handle_native = NULL; + iface->handle_all = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : manager = interface à manipuler. * +* * +* Description : Accompagne la fin du chargement des modules natifs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *manager) +{ + GPluginManagerInterface *iface; /* Interface utilisée */ + + iface = G_PLUGIN_MANAGER_GET_IFACE(manager); + + if (iface->handle_native != NULL) + iface->handle_native(manager); + +} + + +/****************************************************************************** +* * +* Paramètres : manager = interface à manipuler. * +* * +* Description : Prend acte du chargement de l'ensemble des greffons. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *manager) +{ + GPluginManagerInterface *iface; /* Interface utilisée */ + + iface = G_PLUGIN_MANAGER_GET_IFACE(manager); + + if (iface->handle_all != NULL) + iface->handle_all(manager); + +} diff --git a/src/plugins/manager.h b/src/plugins/manager.h new file mode 100644 index 0000000..2eb90a8 --- /dev/null +++ b/src/plugins/manager.h @@ -0,0 +1,61 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * manager.h - prototypes pour l'intervention dans la gestion des extensions + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_MANAGER_H +#define _PLUGINS_MANAGER_H + + +#include "../glibext/helpers.h" + + + +/* -------------------- INTERVENTION DANS LA GESTION DE GREFFONS -------------------- */ + + +#define G_TYPE_PLUGIN_MANAGER (g_plugin_manager_get_type()) + +DECLARE_INTERFACE(GPluginManager, g_plugin_manager, G, PLUGIN_MANAGER); + + +/* Accompagne la fin du chargement des modules natifs. */ +void g_plugin_manager_handle_native_plugins_loaded_event(GPluginManager *); + +/* Prend acte du chargement de l'ensemble des greffons. */ +void g_plugin_manager_handle_all_plugins_loaded_event(GPluginManager *); + + + +/* -------------------- SOLLICITATION DES FONCTIONNALITES CREEES -------------------- */ + + +#define notify_native_plugins_loaded() \ + process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \ + g_plugin_manager_handle_native_plugins_loaded_event) + +#define notify_all_plugins_loaded() \ + process_all_plugins_for(G_TYPE_PLUGIN_MANAGER, G_PLUGIN_MANAGER, \ + g_plugin_manager_handle_all_plugins_loaded_event) + + + +#endif /* _PLUGINS_MANAGER_H */ diff --git a/src/plugins/native-int.h b/src/plugins/native-int.h new file mode 100644 index 0000000..8b8e0eb --- /dev/null +++ b/src/plugins/native-int.h @@ -0,0 +1,62 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * native-int.h - prototypes pour les structures internes des greffons natifs + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _PLUGINS_NATIVE_INT_H +#define _PLUGINS_NATIVE_INT_H + + +#include "native.h" + + +#include "plugin-int.h" + + + +/* Marqueur identifiable */ +#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de + + +/* Greffon natif pour Chrysalide (instance) */ +struct _GNativePlugin +{ + GPluginModule parent; /* A laisser en premier */ + + GModule *module; /* Abstration de manipulation */ + +}; + + +/* Greffon natif pour Chrysalide (classe) */ +struct _GNativePluginClass +{ + GPluginModuleClass parent; /* A laisser en premier */ + +}; + + +/* Met en place un greffon natif. */ +bool g_native_plugin_create(GNativePlugin *, const char *, const char *, const char *, const char *, const char * const *, size_t, GModule *); + + + +#endif /* _PLUGINS_NATIVE_INT_H */ diff --git a/src/plugins/native.c b/src/plugins/native.c new file mode 100644 index 0000000..fedccbe --- /dev/null +++ b/src/plugins/native.c @@ -0,0 +1,278 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * native.c - interactions avec un greffon natif donné + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "native.h" + + +#include "native-int.h" +#include "../common/cpp.h" + + + +/* ------------------------- COMPOSITION DE NOUVEAU GREFFON ------------------------- */ + + +/* Initialise la classe des greffons natifs. */ +static void g_native_plugin_class_init(GNativePluginClass *); + +/* Initialise une instance de greffon natif. */ +static void g_native_plugin_init(GNativePlugin *); + +/* Supprime toutes les références externes. */ +static void g_native_plugin_dispose(GNativePlugin *); + +/* Procède à la libération totale de la mémoire. */ +static void g_native_plugin_finalize(GNativePlugin *); + + + +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Pointe le fichier contenant le greffon manipulé. */ +static char *g_native_plugin_get_filename(const GNativePlugin *); + +/* Fournit le nom brut associé au greffon. */ +static char *g_native_plugin_get_modname(const GNativePlugin *); + + + +/* ---------------------------------------------------------------------------------- */ +/* COMPOSITION DE NOUVEAU GREFFON */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini pour un greffon Python. */ +G_DEFINE_TYPE(GNativePlugin, g_native_plugin, G_TYPE_PLUGIN_MODULE); + + + +/****************************************************************************** +* * +* Paramètres : class = classe à initialiser. * +* * +* Description : Initialise la classe des greffons natifs. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_native_plugin_class_init(GNativePluginClass *class) +{ + GObjectClass *object; /* Autre version de la classe */ + GPluginModuleClass *plugin; /* Version parente de la classe*/ + + object = G_OBJECT_CLASS(class); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_native_plugin_dispose; + object->finalize = (GObjectFinalizeFunc)g_native_plugin_finalize; + + plugin = G_PLUGIN_MODULE_CLASS(class); + + plugin->get_filename = (get_plugin_filename_fc)g_native_plugin_get_filename; + plugin->get_modname = (get_plugin_modname_fc)g_native_plugin_get_modname; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = instance à initialiser. * +* * +* Description : Initialise une instance de greffon natif. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_native_plugin_init(GNativePlugin *plugin) +{ + plugin->module = NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_native_plugin_dispose(GNativePlugin *plugin) +{ + if (plugin->module != NULL) + { + g_module_close(plugin->module); + plugin->module = NULL; + } + + G_OBJECT_CLASS(g_native_plugin_parent_class)->dispose(G_OBJECT(plugin)); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_native_plugin_finalize(GNativePlugin *plugin) +{ + G_OBJECT_CLASS(g_native_plugin_parent_class)->finalize(G_OBJECT(plugin)); + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = instance à initialiser pleinement. * +* name = nom du greffon pour référence, principalement. * +* desc = présentation éventuelle à destination humaine. * +* version = indication de version éventuelle. * +* url = référence vers une ressource en ligne. * +* required = liste de dépendances éventuelles ou NULL. * +* count = taille de cette liste. * +* module = extension vue du système. * +* * +* Description : Met en place un greffon natif. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : Le transfert de propriétée du module est total. * +* * +******************************************************************************/ + +bool g_native_plugin_create(GNativePlugin *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count, GModule *module) +{ + bool result; /* Bilan à retourner */ + + result = g_plugin_module_create(G_PLUGIN_MODULE(plugin), name, desc, version, url, required, count); + + if (result) + plugin->module = module; + + return result; + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Pointe le fichier contenant le greffon manipulé. * +* * +* Retour : Chemin d'accès au greffon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_native_plugin_get_filename(const GNativePlugin *plugin) +{ + char *result; /* Chemin d'accès à renvoyer */ + + result = strdup(g_module_name(plugin->module)); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : plugin = greffon à valider. * +* * +* Description : Fournit le nom brut associé au greffon. * +* * +* Retour : Désignation brute du greffon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static char *g_native_plugin_get_modname(const GNativePlugin *plugin) +{ + char *result; /* Désignation brute à renvoyer*/ + char *path; /* Chemin à traiter */ + char *filename; /* Nom de bibliothèque partagée*/ + size_t length; /* Taille du nom */ + int ret; /* Bilan d'une comparaison */ + + path = g_native_plugin_get_filename(plugin); + + filename = basename(path); + + if (strncmp(filename, "lib", 3) == 0) + filename += 3; + + length = strlen(filename); + +#ifdef _WIN32 +# define SHARED_SUFFIX ".dll" +#else +# define SHARED_SUFFIX ".so" +#endif + + if (length >= STATIC_STR_SIZE(SHARED_SUFFIX)) + { + ret = strncmp(&filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)], + SHARED_SUFFIX, + STATIC_STR_SIZE(SHARED_SUFFIX)); + + if (ret == 0) + filename[length - STATIC_STR_SIZE(SHARED_SUFFIX)] = '\0'; + + } + + result = strdup(filename); + + free(path); + + return result; + +} diff --git a/src/plugins/native.h b/src/plugins/native.h new file mode 100644 index 0000000..205342c --- /dev/null +++ b/src/plugins/native.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * native.h - prototypes pour les interactions avec un greffon natif donné + * + * Copyright (C) 2025 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef _PLUGINS_NATIVE_H +#define _PLUGINS_NATIVE_H + + +#include "../glibext/helpers.h" + + + +#define G_TYPE_NATIVE_PLUGIN (g_native_plugin_get_type()) + +DECLARE_GTYPE(GNativePlugin, g_native_plugin, G, NATIVE_PLUGIN); + + + +#endif /* _PLUGINS_NATIVE_H */ diff --git a/src/plugins/pglist.c b/src/plugins/pglist.c index e4cb825..083f11f 100644 --- a/src/plugins/pglist.c +++ b/src/plugins/pglist.c @@ -30,20 +30,29 @@ #include <malloc.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <i18n.h> #include "dt.h" +#include "manager.h" #include "plugin-int.h" -#include "../common/extstr.h" +#include "../common/cpp.h" +#include "../common/extstr.h" // REMME ? #include "../core/logs.h" #include "../core/nox.h" #include "../core/paths.h" +/** + * Prototype de la fonction de création, à garder synchronisé avec + * NATIVE_PLUGIN_ENTRYPOINT() (cf. native-int.h). + */ +typedef GPluginModule * (* get_plugin_instance_cb) (GModule *); + /* Liste de l'ensemble des greffons */ static GPluginModule **_pg_list = NULL; static size_t _pg_count = 0; @@ -129,6 +138,10 @@ bool init_all_plugins(bool load) void exit_all_plugins(void) { + +#if 0 ////// + + size_t i; /* Boucle de parcours */ const plugin_interface *pg_iface; /* Définition du greffon */ @@ -188,6 +201,10 @@ void exit_all_plugins(void) exit_chrysalide_dynamic_types(); + + +#endif + } @@ -244,83 +261,95 @@ static int filter_dirs_or_mods(const struct dirent *entry) * * * Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). * * * -* Description : Part à la recherche de greffons sous forme de modules. * +* Description : Indique la version (NOX/UI) associée à un nom de fichier. * * * -* Retour : - * +* Retour : true si la version complémentaire existe ou false. * * * * Remarques : - * * * ******************************************************************************/ -static void browse_directory_for_plugins(const char *dir) +static bool check_for_plugin_versions(const char *dir, const char *filename, bool *is_nox, bool *is_ui) { - struct dirent **namelist; /* Eléments trouvés */ - int ret; /* Bilan du parcours */ - bool nox; /* Absence de support graphique*/ - char *filename; /* Elément à ausculter */ - GPluginModule *plugin; /* Greffon à intégrer ou pas */ - - ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort); - if (ret < 0) - { - LOG_ERROR_N("scandir"); - return; - } - - nox = run_in_nox_mode(); + bool result; /* Bilan à renvoyer */ + size_t length; /* Taille du nom de fichier */ + char *alt_path; /* Autre chemin complet testé */ + int ret; /* Bilan d'une impression */ - while (ret--) - { - - if (nox) - { #ifdef _WIN32 -# define UI_SHARED_SUFFIX "-ui.dll" +# define SHARED_SUFFIX ".dll" #else -# define UI_SHARED_SUFFIX "-ui.so" +# define SHARED_SUFFIX ".so" #endif +#define UI_SHARED_SUFFIX "ui" SHARED_SUFFIX - if (strstr(namelist[ret]->d_name, UI_SHARED_SUFFIX) != NULL) - { - log_variadic_message(LMT_ERROR, _("Skipping unsuitable file: %s"), namelist[ret]->d_name); - continue; - } + result = false; - } + /* Propriétés du fichier courant */ - filename = (char *)calloc(strlen(dir) + 1 + strlen(namelist[ret]->d_name) + 1, sizeof(char)); + length = strlen(filename); - strcpy(filename, dir); - strcat(filename, G_DIR_SEPARATOR_S); - strcat(filename, namelist[ret]->d_name); + if (length < STATIC_STR_SIZE(UI_SHARED_SUFFIX)) + *is_ui = false; - if (namelist[ret]->d_type == DT_DIR) - browse_directory_for_plugins(filename); + else + *is_ui = (strcmp(filename + length - STATIC_STR_SIZE(UI_SHARED_SUFFIX), UI_SHARED_SUFFIX) == 0); + + if (*is_ui) + *is_nox = false; + + else + { + if (length < STATIC_STR_SIZE(SHARED_SUFFIX)) + *is_nox = false; else - { - plugin = g_plugin_module_new(filename); + *is_nox = (strcmp(filename + length - STATIC_STR_SIZE(SHARED_SUFFIX), SHARED_SUFFIX) == 0); - if (plugin != NULL) - register_plugin(plugin); + } + + /* Recherche d'une version alternative */ + if (*is_nox || *is_ui) + { + + if (*is_nox) + ret = asprintf(&alt_path, "%s%s%.*s%s", + dir, G_DIR_SEPARATOR_S, + (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename, + UI_SHARED_SUFFIX); + else + ret = asprintf(&alt_path, "%s%s%.*s%s", + dir, G_DIR_SEPARATOR_S, + (int)(length - STATIC_STR_SIZE(SHARED_SUFFIX)), filename, + SHARED_SUFFIX); + + if (ret <= 0) + { + LOG_ERROR_N("asprintf"); + goto exit; } - free(filename); - free(namelist[ret]); + ret = access(alt_path, R_OK | X_OK); + + result = (ret == 0); + + free(alt_path); } - free(namelist); + exit: + + return result; } /****************************************************************************** * * -* Paramètres : plugin = greffon à ajouter aux autres disponibles. * +* Paramètres : dir = répertoire à parcourir en quête de greffons (sans /). * * * -* Description : Ajoute un greffon à la liste principale de greffons. * +* Description : Part à la recherche de greffons sous forme de modules. * * * * Retour : - * * * @@ -328,52 +357,117 @@ static void browse_directory_for_plugins(const char *dir) * * ******************************************************************************/ -void _register_plugin(GPluginModule *plugin) +static void browse_directory_for_plugins(const char *dir) { - size_t i; /* Boucle de parcours */ - const plugin_interface *pg_iface; /* Informations à consulter */ - const char *name; /* Désignation du greffon */ - - /** - * L'appel sans verrou n'est fourni que pour les greffons - * mettant en place des greffons en interne ! - */ - - /* Recherche d'un éventuel doublon */ + struct dirent **namelist; /* Eléments trouvés */ + int ret; /* Bilan d'un appel */ + int k; /* Boucle de parcours */ + bool nox_mode; /* Absence de support graphique*/ + char *filename; /* Elément à ausculter */ + bool is_nox; /* Chemin de version basique ? */ + bool is_ui; /* Chemin de version graphique */ + bool has_alt; /* Existence d'une alternative */ + GModule *module; /* Abstration de manipulation */ + get_plugin_instance_cb get_instance; /* Point d'entrée exporté */ + GPluginModule *plugin; /* Greffon à intégrer ou pas */ - pg_iface = g_plugin_module_get_interface(plugin); + ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort); + if (ret < 0) + { + LOG_ERROR_N("scandir"); + return; + } - name = pg_iface->name; + nox_mode = run_in_nox_mode(); - for (i = 0; i < _pg_count; i++) + for (k = ret; k--; ) { - pg_iface = g_plugin_module_get_interface(_pg_list[i]); + ret = asprintf(&filename, "%s%s%s", dir, G_DIR_SEPARATOR_S, namelist[k]->d_name); + if (ret <= 0) + { + LOG_ERROR_N("asprintf"); + continue; + } + + if (namelist[k]->d_type == DT_DIR) + browse_directory_for_plugins(filename); - if (strcmp(name, pg_iface->name) == 0) + else { - log_variadic_message(LMT_ERROR, - _("Plugin '%s' already registered!"), name); - break; + printf("// Candidate // %s\n", filename); - } + has_alt = check_for_plugin_versions(dir, namelist[k]->d_name, &is_nox, &is_ui); - } + printf(" -> nox=%d ui=%d -> alt? %d\n", is_nox, is_ui, has_alt); - /* Ajout du greffon à la liste */ - if (i == _pg_count) - { - _pg_list = (GPluginModule **)realloc(_pg_list, ++_pg_count * sizeof(GPluginModule)); + if ((nox_mode && is_nox) || (!nox_mode && ((is_nox && !has_alt) || is_ui))) + { + + + printf(" ---> load!\n"); - _pg_list[_pg_count - 1] = plugin; - g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL); + + module = g_module_open(filename, G_MODULE_BIND_LAZY); + if (module == NULL) + { + log_variadic_message(LMT_ERROR, + _("Error while loading the plugin candidate '%s' : %s"), + filename, g_module_error()); + goto next_file; + } + + + printf(" (main) module=%p '%s'\n", module, g_module_name(module)); + + + if (!g_module_symbol(module, "get_chrysalide_plugin_instance", (gpointer *)&get_instance)) + { + log_variadic_message(LMT_ERROR, + _("No '%s' entry in plugin candidate '%s'"), + "<sym>", filename); + + + + } + + + if (get_instance == NULL) + plugin = NULL; + else + plugin = get_instance(module); + + + + printf(" ===> plugin: %p\n", plugin); + + + + if (plugin != NULL) + { + register_plugin(plugin); + unref_object(plugin); + } + + else + g_module_close(module); + + } + else + log_variadic_message(LMT_INFO, _("Skipping unsuitable file for plugin: %s"), filename); + + } + + next_file: + + free(filename); + free(namelist[k]); } - else - /* FIXME : leak(plugin); */; + free(namelist); } @@ -394,7 +488,7 @@ void _register_plugin(GPluginModule *plugin) static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolean last) { - const plugin_interface *pg_iface; /* Vitrine d'un greffon */ + const char *name; /* Désignation du greffon */ size_t index; /* Indice du greffon */ GPluginModule *same; /* Juste pour la récupération */ @@ -402,16 +496,17 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea { assert(g_rw_lock_writer_trylock(&_pg_lock) == FALSE); - pg_iface = g_plugin_module_get_interface(plugin); + name = g_plugin_module_get_name(plugin); - same = get_plugin_by_name(pg_iface->name, &index); + same = get_plugin_by_name(name, &index); assert(same != NULL); + assert(same == plugin); - _pg_list[index] = NULL; + g_clear_object(&_pg_list[index]); - g_object_remove_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL); + g_object_remove_toggle_ref(G_OBJECT(same), (GToggleNotify)on_plugin_ref_toggle, NULL); - g_object_unref(G_OBJECT(same)); + unref_object(same); } @@ -432,9 +527,40 @@ static void on_plugin_ref_toggle(gpointer unused, GPluginModule *plugin, gboolea void register_plugin(GPluginModule *plugin) { + size_t i; /* Boucle de parcours */ + const char *name; /* Désignation du greffon */ + const char *existing; /* Nom d'un greffon en place */ + g_rw_lock_writer_lock(&_pg_lock); - _register_plugin(plugin); + /* Recherche d'un éventuel doublon */ + + name = g_plugin_module_get_name(plugin); + + for (i = 0; i < _pg_count; i++) + { + existing = g_plugin_module_get_name(_pg_list[i]); + + if (strcmp(name, existing) == 0) + { + log_variadic_message(LMT_ERROR, _("Plugin '%s' already registered!"), name); + break; + } + + } + + /* Ajout du greffon à la liste */ + + if (i == _pg_count) + { + _pg_list = realloc(_pg_list, ++_pg_count * sizeof(GPluginModule)); + + _pg_list[_pg_count - 1] = plugin; + ref_object(plugin); + + g_object_add_toggle_ref(G_OBJECT(plugin), (GToggleNotify)on_plugin_ref_toggle, NULL); + + } g_rw_lock_writer_unlock(&_pg_lock); @@ -543,7 +669,7 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index) { GPluginModule *result; /* Greffon trouvé à renvoyer */ size_t i; /* Boucle de parcours */ - const plugin_interface *pg_iface; /* Vitrine d'un greffon */ + const char *current; /* Nom du greffon courant */ result = NULL; @@ -557,11 +683,12 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index) /* Si on est en train de procéder à un nettoyage... */ if (_pg_list[i] == NULL) continue; - pg_iface = g_plugin_module_get_interface(_pg_list[i]); + current = g_plugin_module_get_name(_pg_list[i]); - if (strcmp(pg_iface->name, name) == 0) + if (strcmp(current, name) == 0) { result = _pg_list[i]; + ref_object(result); if (index != NULL) *index = i; @@ -570,9 +697,6 @@ GPluginModule *get_plugin_by_name(const char *name, size_t *index) } - if (result != NULL) - g_object_ref(G_OBJECT(result)); - return result; } @@ -603,60 +727,7 @@ GPluginModule **get_all_plugins(size_t *count) for (i = 0; i < _pg_count; i++) { result[i] = _pg_list[i]; - g_object_ref(G_OBJECT(_pg_list[i])); - } - - g_rw_lock_reader_unlock(&_pg_lock); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : action = fonctionnalité recherchée. * -* count = nombre de greffons trouvés. [OUT] * -* * -* Description : Fournit les greffons offrant le service demandé. * -* * -* Retour : Liste de greffons correspondants issue d'un tri interne. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count) -{ - GPluginModule **result; /* Liste à retourner */ - size_t i; /* Boucle de parcours #1 */ - const plugin_interface *pg_iface; /* Informations à consulter */ - size_t j; /* Boucle de parcours #2 */ - - result = NULL; - *count = 0; - - g_rw_lock_reader_lock(&_pg_lock); - - for (i = 0; i < _pg_count; i++) - { - pg_iface = g_plugin_module_get_interface(_pg_list[i]); - - for (j = 0; j < pg_iface->actions_count; j++) - { - if (pg_iface->actions[j] == action) - { - result = realloc(result, ++(*count) * sizeof(GPluginModule *)); - - result[*count - 1] = _pg_list[i]; - g_object_ref(G_OBJECT(_pg_list[i])); - - break; - - } - - } - + ref_object(result[i]); } g_rw_lock_reader_unlock(&_pg_lock); diff --git a/src/plugins/pglist.h b/src/plugins/pglist.h index 83e9091..5541493 100644 --- a/src/plugins/pglist.h +++ b/src/plugins/pglist.h @@ -52,9 +52,6 @@ void _lock_unlock_plugin_list_for_reading(bool lock); #define unlock_plugin_list_for_reading() _lock_unlock_plugin_list_for_reading(false) /* Ajoute un greffon à la liste principale de greffons. */ -void _register_plugin(GPluginModule *); - -/* Ajoute un greffon à la liste principale de greffons. */ void register_plugin(GPluginModule *); /* Charge tous les greffons restant à charger. */ @@ -66,16 +63,39 @@ GPluginModule *get_plugin_by_name(const char *, size_t *); /* Fournit la liste de l'ensemble des greffons. */ GPluginModule **get_all_plugins(size_t *); -/* Fournit les greffons offrant le service demandé. */ -GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); - /** * Définitions des opérations appliquables à une catégories de greffons. */ -#define process_all_plugins_for(a, f, ...) \ +#define process_all_plugins_for(tp, cst, fc) \ + do \ + { \ + size_t __count; \ + GPluginModule **__list; \ + size_t __i; \ + __list = get_all_plugins(&__count); \ + for (__i = 0; __i < __count; __i++) \ + { \ + if (G_TYPE_CHECK_INSTANCE_TYPE(__list[__i], tp)) \ + fc(cst(__list[__i])); \ + unref_object(__list[__i]); \ + } \ + if (__list != NULL) \ + free(__list); \ + } \ + while (0) + + + + + +#if 0 + +// TODO : REMME + +#define process_all_plugins_for_old__(a, f, ...) \ do \ { \ size_t __count; \ @@ -114,11 +134,13 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); /* DPS_PG_MANAGEMENT */ +/* #define notify_native_plugins_loaded() \ - process_all_plugins_for(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) + process_all_plugins_for_old__(PGA_NATIVE_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) #define notify_all_plugins_loaded() \ - process_all_plugins_for(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) + process_all_plugins_for_old__(PGA_ALL_PLUGINS_LOADED, g_plugin_module_notify_plugins_loaded, NULL) +*/ #define build_type_instance(t) \ process_plugins_while_null(PGA_TYPE_BUILDING, g_plugin_module_build_type_instance, t) @@ -126,44 +148,47 @@ GPluginModule **get_all_plugins_for_action(PluginAction, size_t *); /* DPS_SETUP */ #define include_plugin_theme(d, r, c) \ - process_all_plugins_for(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c) + process_all_plugins_for_old__(PGA_GUI_THEME, g_plugin_module_include_theme, d, r, c) /* DPS_RUNNING */ #define notify_panel_creation(i) \ - process_all_plugins_for(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i) + process_all_plugins_for_old__(PGA_PANEL_CREATION, g_plugin_module_notify_panel_creation, i) #define notify_panel_docking(i, d) \ - process_all_plugins_for(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d) + process_all_plugins_for_old__(PGA_PANEL_DOCKING, g_plugin_module_notify_panel_docking, i, d) /* DPS_CONTENT */ #define handle_binary_content(a, c, i, s) \ - process_all_plugins_for(a, g_plugin_module_handle_binary_content, c, i, s) + process_all_plugins_for_old__(a, g_plugin_module_handle_binary_content, c, i, s) #define handle_loaded_content(a, c, i, s) \ - process_all_plugins_for(a, g_plugin_module_handle_loaded_content, c, i, s) + process_all_plugins_for_old__(a, g_plugin_module_handle_loaded_content, c, i, s) /* DPS_FORMAT */ #define handle_known_format_analysis(a, f, g, s) \ - process_all_plugins_for(a, g_plugin_module_handle_known_format_analysis, f, g, s) + process_all_plugins_for_old__(a, g_plugin_module_handle_known_format_analysis, f, g, s) #define preload_binary_format(a, f, i, s) \ - process_all_plugins_for(a, g_plugin_module_preload_binary_format, f, i, s) + process_all_plugins_for_old__(a, g_plugin_module_preload_binary_format, f, i, s) #define attach_debug_format(f) \ - process_all_plugins_for(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f) + process_all_plugins_for_old__(PGA_FORMAT_ATTACH_DEBUG, g_plugin_module_attach_debug_format, f) /* DPS_DISASSEMBLY */ #define process_disassembly_event(a, b, s, c) \ - process_all_plugins_for(a, g_plugin_module_process_disassembly_event, b, s, c) + process_all_plugins_for_old__(a, g_plugin_module_process_disassembly_event, b, s, c) /* DPS_DETECTION */ #define detect_external_tools(a, cnt, v, n, c) \ - process_all_plugins_for(a, g_plugin_module_detect_external_tools, cnt, v, n, c) + process_all_plugins_for_old__(a, g_plugin_module_detect_external_tools, cnt, v, n, c) + + +#endif diff --git a/src/plugins/plugin-def.h b/src/plugins/plugin-def.h index 1118140..b5e0b51 100644 --- a/src/plugins/plugin-def.h +++ b/src/plugins/plugin-def.h @@ -35,18 +35,6 @@ /* ------------------------ IDENTIFICATION DE COMPATIBILITES ------------------------ */ -/* Version identifiant les définitions courantes */ -typedef uint32_t plugin_abi_version_t; - -#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \ - (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff)) - -#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff) -#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff) -#define GET_ABI_REV_VERSION(vs) (vs & 0xffff) - -#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(0, 3, 0) - /* ------------------------- DEFINITION D'UN PROJET INTERNE ------------------------- */ @@ -232,14 +220,14 @@ typedef enum _PluginAction /* ------------------------ PREMIER INTERFACAGE PROTOCOLAIRE ------------------------ */ -#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull +//#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de1234abcdull /* Définition d'un greffon */ typedef struct _plugin_interface { uint64_t magic; /* Vérification a minima */ - plugin_abi_version_t abi_version; /* Version du protocole utilisé*/ + uint32_t /*plugin_abi_version_t*/ abi_version; /* Version du protocole utilisé*/ /** * Les champs suivants ne sont généralement pas alloués dynamiquement, diff --git a/src/plugins/plugin-int.h b/src/plugins/plugin-int.h index 3ba19dc..07b455a 100644 --- a/src/plugins/plugin-int.h +++ b/src/plugins/plugin-int.h @@ -37,21 +37,28 @@ #include "../common/bits.h" -/* Transfert de la conscience de soi. */ -typedef void (* pg_set_self_fc) (GPluginModule *); -/* Prend acte du [dé]chargement du greffon. */ +/* Pointe le fichier contenant le greffon manipulé. */ +typedef char * (* get_plugin_filename_fc) (const GPluginModule *); + +/* Fournit le nom brut associé au greffon. */ +typedef char * (* get_plugin_modname_fc) (const GPluginModule *); + +/* Prend acte de (l'|la dés)activation du greffon. */ typedef bool (* pg_management_fc) (GPluginModule *); + + + +/* Transfert de la conscience de soi. */ +typedef void (* pg_set_self_fc) (GPluginModule *); + /* Accompagne la fin du chargement des modules natifs. */ typedef void (* pg_plugins_loaded_fc) (GPluginModule *, PluginAction); /* Crée une instance à partir d'un type dynamique externe. */ typedef gpointer (* pg_build_instance_fc) (GPluginModule *, PluginAction, GType); -/* Fournit le nom brut associé au greffon. */ -typedef char * (* pg_get_modname_fc) (const GPluginModule *); - #if 0 /* Procède à une opération liée à un contenu binaire. */ @@ -90,22 +97,47 @@ typedef void (* pg_detect_tools_fc) (const GPluginModule *, PluginAction, const #endif +/* Marqueur identifiable */ +#define CHRYSALIDE_PLUGIN_MAGIC 0xdeadc0de + + +/* Version identifiant les définitions courantes */ +typedef uint32_t plugin_abi_version_t; + +#define DEFINE_PLUGIN_ABI_VERSION(maj, min, rev) \ + (((maj & 0xff) << 24) | ((min & 0xff) << 16) | (rev & 0xffff)) + +#define GET_ABI_MAJ_VERSION(vs) ((vs >> 24) & 0xff) +#define GET_ABI_MIN_VERSION(vs) ((vs >> 16) & 0xff) +#define GET_ABI_REV_VERSION(vs) (vs & 0xffff) + +/** + * 0.3.0 : dernière version avec actions et fonctions associées + * 1.0.0 (04/01/25) : bascule en chargement d'objet et interfaces + */ +#define CURRENT_ABI_VERSION DEFINE_PLUGIN_ABI_VERSION(1, 0, 0) + + /* Greffon pour Chrysalide (instance) */ struct _GPluginModule { GObject parent; /* A laisser en premier */ - char *filename; /* Fichier associé au greffon */ - GModule *module; /* Abstration de manipulation */ + uint32_t magic; /* Vérification a minima */ + plugin_abi_version_t abi_version; /* Version du protocole utilisé*/ + + char *name; /* Désignation humaine courte */ + char *desc; /* Description plus loquace */ + char *version; /* Version du greffon */ + char *url; /* Site Web associé */ - const plugin_interface *interface; /* Déclaration d'interfaçage */ + char **required; /* Pré-chargements requis */ + size_t required_count; /* Quantité de ces dépendances */ PluginStatusFlags flags; /* Fanion pour l'état courant */ bitfield_t *dependencies; /* Cartographie des dépendances*/ - //GGenConfig *config; /* Configuration dédiée */ - }; @@ -114,6 +146,18 @@ struct _GPluginModuleClass { GObjectClass parent; /* A laisser en premier */ + get_plugin_filename_fc get_filename; /* Obtention du chemin */ + get_plugin_modname_fc get_modname; /* Fourniture du nom brut */ + + pg_management_fc enable; /* Procédure d'activation */ + pg_management_fc disable; /* Procédure d'extinction */ + + + + ///////////////////////////////////////////// + +#if 0 + pg_management_fc init; /* Procédure d'initialisation */ pg_management_fc manage; /* Etape dans la vie du greffon*/ pg_management_fc exit; /* Procédure d'extinction */ @@ -121,8 +165,6 @@ struct _GPluginModuleClass pg_plugins_loaded_fc plugins_loaded; /* Fin des chargements */ pg_build_instance_fc build_instance; /* Création d'objets */ - pg_get_modname_fc get_modname; /* Fourniture du nom brut */ - #if 0 #ifdef INCLUDE_GTK_SUPPORT pg_include_theme_fc include_theme; /* Extension d'un thème */ @@ -141,12 +183,28 @@ struct _GPluginModuleClass pg_detect_tools_fc detect; /* Lancement de détections */ #endif +#endif + + ///////////////////////////////////////////// + }; -/* Met en place la configuration dédiée au greffon. */ -void g_plugin_module_create_config(GPluginModule *); + +#define STORE_PLUGIN_ABI(p) \ + do \ + { \ + GPluginModule *_p; \ + _p = G_PLUGIN_MODULE(p); \ + _p->magic = CHRYSALIDE_PLUGIN_MAGIC; \ + _p->abi_version = CURRENT_ABI_VERSION; \ + } \ + while (0); + + +/* Met en place un greffon. */ +bool g_plugin_module_create(GPluginModule *, const char *, const char *, const char *, const char *, const char * const *, size_t); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 75cf4e0..c537bc3 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -30,7 +30,6 @@ #include <libgen.h> #include <malloc.h> #include <stdarg.h> -#include <stdbool.h> #include <stdio.h> #include <string.h> @@ -38,6 +37,7 @@ #include "dt.h" #include "pglist.h" #include "plugin-int.h" +#include "../common/compiler.h" #include "../common/extstr.h" #include "../common/pathname.h" #include "../common/xdg.h" @@ -56,19 +56,12 @@ static void g_plugin_module_dispose(GPluginModule *); /* Procède à la libération totale de la mémoire. */ static void g_plugin_module_finalize(GPluginModule *); -/* Initialise la classe des greffons d'extension. */ -static void g_plugin_module_init_gclass(GPluginModuleClass *, GModule *); - -/* Fournit le nom brut associé au greffon. */ -static char *_g_plugin_module_get_modname(const GPluginModule *); - /* Indique le type défini pour un greffon. */ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT); - /****************************************************************************** * * * Paramètres : class = classe à initialiser. * @@ -84,16 +77,17 @@ G_DEFINE_TYPE(GPluginModule, g_plugin_module, G_TYPE_OBJECT); static void g_plugin_module_class_init(GPluginModuleClass *class) { GObjectClass *object; /* Autre version de la classe */ - GPluginModuleClass *plugin; /* Version parente de la classe*/ object = G_OBJECT_CLASS(class); object->dispose = (GObjectFinalizeFunc/* ! */)g_plugin_module_dispose; object->finalize = (GObjectFinalizeFunc)g_plugin_module_finalize; - plugin = G_PLUGIN_MODULE_CLASS(class); + class->get_filename = NULL; + class->get_modname = NULL; - plugin->get_modname = (pg_get_modname_fc)_g_plugin_module_get_modname; + class->enable = NULL; + class->disable = NULL; } @@ -112,7 +106,17 @@ static void g_plugin_module_class_init(GPluginModuleClass *class) static void g_plugin_module_init(GPluginModule *plugin) { - //plugin->config = NULL; + plugin->name = NULL; + plugin->desc = NULL; + plugin->version = NULL; + plugin->url = NULL; + + plugin->required = NULL; + plugin->required_count = 0; + + plugin->flags = PSF_NONE; + + plugin->dependencies = NULL; } @@ -131,58 +135,35 @@ static void g_plugin_module_init(GPluginModule *plugin) static void g_plugin_module_dispose(GPluginModule *plugin) { - const plugin_interface *pg_iface; /* Définition du greffon */ size_t i; /* Boucle de parcours */ GPluginModule *dependency; /* Module nécessaire */ GPluginModuleClass *class; /* Classe de l'instance active */ - pg_iface = g_plugin_module_get_interface(plugin); + lock_plugin_list_for_reading(); - if (pg_iface != NULL) + for (i = 0; i < plugin->required_count; i++) { - lock_plugin_list_for_reading(); + dependency = get_plugin_by_name(plugin->required[i], NULL); - for (i = 0; i < pg_iface->required_count; i++) + /* Si le chargement a bien été complet avant la sortie... */ + if (dependency != NULL) { - dependency = get_plugin_by_name(pg_iface->required[i], NULL); + /* Un coup pour l'appel à get_plugin_by_name(). */ + unref_object(dependency); - /* Si le chargement a bien été complet avant la sortie... */ - if (dependency != NULL) - { - /* Un coup pour l'appel à get_plugin_by_name(). */ - g_object_unref(G_OBJECT(dependency)); - - /* Un coup pour la dépendance */ - g_object_unref(G_OBJECT(dependency)); - - } + /* Un coup pour la dépendance */ + unref_object(dependency); } - unlock_plugin_list_for_reading(); - } - class = G_PLUGIN_MODULE_GET_CLASS(plugin); + unlock_plugin_list_for_reading(); - if (class->exit != NULL) - class->exit(plugin); - - /* - if (plugin->config != NULL) - { - g_generic_config_write(plugin->config); - - g_clear_object(&plugin->config); + class = G_PLUGIN_MODULE_GET_CLASS(plugin); - } - */ - - if (plugin->module != NULL) - { - g_module_close(plugin->module); - plugin->module = NULL; - } + if (class->disable != NULL) + class->disable(plugin); G_OBJECT_CLASS(g_plugin_module_parent_class)->dispose(G_OBJECT(plugin)); @@ -203,7 +184,25 @@ static void g_plugin_module_dispose(GPluginModule *plugin) static void g_plugin_module_finalize(GPluginModule *plugin) { - free(plugin->filename); + size_t i; /* Boucle de parcours */ + + if (plugin->name != NULL) + free(plugin->name); + + if (plugin->desc != NULL) + free(plugin->desc); + + if (plugin->version != NULL) + free(plugin->version); + + if (plugin->url != NULL) + free(plugin->url); + + for (i = 0; i < plugin->required_count; i++) + free(plugin->required[i]); + + if (plugin->required != NULL) + free(plugin->required); if (plugin->dependencies != NULL) delete_bit_field(plugin->dependencies); @@ -215,627 +214,173 @@ static void g_plugin_module_finalize(GPluginModule *plugin) /****************************************************************************** * * -* Paramètres : filename = nom du fichier à charger. * +* Paramètres : plugin = instance à initialiser pleinement. * +* name = nom du greffon pour référence, principalement. * +* desc = présentation éventuelle à destination humaine. * +* version = indication de version éventuelle. * +* url = référence vers une ressource en ligne. * +* required = liste de dépendances éventuelles ou NULL. * +* count = taille de cette liste. * * * -* Description : Crée un module pour un greffon donné. * +* Description : Met en place un greffon. * * * -* Retour : Adresse de la structure mise en place. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -GPluginModule *g_plugin_module_new(const gchar *filename) +bool g_plugin_module_create(GPluginModule *plugin, const char *name, const char *desc, const char *version, const char *url, const char * const *required, size_t count) { - GPluginModule *result; /* Structure à retourner */ - GModule *module; /* Abstration de manipulation */ - pg_set_self_fc set_self; /* Copie du greffon */ - const plugin_interface *interface; /* Déclaration d'interfaçage */ - plugin_abi_version_t current; /* Version de l'ABI actuelle */ - bool valid; /* Statut de validité */ - size_t i; /* Boucle de parcours */ - uint32_t action; /* Identifiant d'une action */ - uint32_t category; /* Catégorie principale */ - uint32_t sub; /* Sous-catégorie visée */ - GType gtype; /* Nouveau type de greffon */ - - module = g_module_open(filename, G_MODULE_BIND_LAZY); - if (module == NULL) - { - log_variadic_message(LMT_ERROR, - _("Error while loading the plugin candidate '%s' : %s"), - filename, g_module_error()); - goto bad_module; - } - - -#define load_plugin_symbol(mod, sym, dest) \ - ({ \ - bool __result; \ - if (!g_module_symbol(mod, sym, (gpointer *)dest)) \ - { \ - log_variadic_message(LMT_ERROR, \ - _("No '%s' entry in plugin candidate '%s'"), \ - sym, filename); \ - __result = false; \ - } \ - else __result = true; \ - __result; \ - }) - - - /* Récupération de la version d'ABI */ - - if (!load_plugin_symbol(module, "chrysalide_plugin_set_self", &set_self)) - goto no_self_setter; - - if (!load_plugin_symbol(module, "_chrysalide_plugin", &interface)) - goto no_interface; - - current = CURRENT_ABI_VERSION; - - if (current != interface->abi_version) - goto wrong_abi; - - /* Localisation des différents points d'entrée déclarés */ - + bool result; /* Bilan à retourner */ + size_t i; /* Boucle de parcours #1 */ + size_t k; /* Boucle de parcours #2 */ -#define check_plugin_symbol(mod, sym) \ - ({ \ - bool __result; \ - __result = g_module_symbol(mod, sym, (gpointer []) { NULL }); \ - if (!__result) \ - log_variadic_message(LMT_ERROR, \ - _("No '%s' entry in plugin candidate '%s'"), \ - sym, filename); \ - __result; \ - }) + /* Validations préalables */ + assert(name != NULL); - valid = true; + result = (name != NULL); - for (i = 0; i < interface->actions_count && valid; i++) + if (result && plugin->abi_version != CURRENT_ABI_VERSION) { - action = interface->actions[i]; - category = MASK_PLUGIN_CATEGORY(action); - sub = MASK_PLUGIN_SUB_CATEGORY(action); - - switch (category) - { - case DPC_BASIC: - - switch (sub) - { - case DPS_NONE: - break; - - case DPS_PG_MANAGEMENT: - - switch (action) - { - case PGA_PLUGIN_INIT: - valid = check_plugin_symbol(module, "chrysalide_plugin_init"); - break; - - case PGA_PLUGIN_LOADED: - valid = check_plugin_symbol(module, "chrysalide_plugin_manage"); - break; - - case PGA_PLUGIN_EXIT: - valid = check_plugin_symbol(module, "chrysalide_plugin_exit"); - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - interface->actions[i], filename); - break; - - } - - break; - - case DPS_CORE_MANAGEMENT: - - switch (action) - { - case PGA_NATIVE_PLUGINS_LOADED: - case PGA_ALL_PLUGINS_LOADED: - valid = check_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded"); - break; - - case PGA_TYPE_BUILDING: - valid = check_plugin_symbol(module, "chrysalide_plugin_build_type_instance"); - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - interface->actions[i], filename); - break; - - } - - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); - break; - - } - - break; - -#if 0 - - case DPC_GUI: - - switch (sub) - { - case DPS_SETUP: - - switch (action) - { - case PGA_GUI_THEME: - valid = check_plugin_symbol(module, "chrysalide_plugin_include_theme"); - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - interface->actions[i], filename); - break; - - } - - break; - - case DPS_RUNNING: - - switch (action) - { - case PGA_PANEL_CREATION: - valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_creation"); - break; - - case PGA_PANEL_DOCKING: - valid = check_plugin_symbol(module, "chrysalide_plugin_on_panel_docking"); - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - interface->actions[i], filename); - break; - - } - - break; - - default: - log_variadic_message(LMT_WARNING, - _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); - break; - - } - - break; - - case DPC_BINARY_PROCESSING: - - switch (sub) - { - case DPS_CONTENT: - - switch (action) - { - case PGA_CONTENT_EXPLORER: - case PGA_CONTENT_RESOLVER: - valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_content"); - break; + result = false; - case PGA_CONTENT_ANALYZED: - valid = check_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content"); - break; + log_variadic_message(LMT_ERROR, _("ABI mismatch detected: %08x (plugin) vs %08x (core)"), + plugin->abi_version, CURRENT_ABI_VERSION); - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - interface->actions[i], filename); - break; - - } - - break; - - case DPS_FORMAT: - - switch (action) - { - case PGA_FORMAT_ANALYSIS_STARTED: - case PGA_FORMAT_ANALYSIS_ENDED: - case PGA_FORMAT_POST_ANALYSIS_STARTED: - case PGA_FORMAT_POST_ANALYSIS_ENDED: - valid = check_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis"); - break; - - case PGA_FORMAT_PRELOAD: - valid = check_plugin_symbol(module, "chrysalide_plugin_preload_binary_format"); - break; + } - case PGA_FORMAT_ATTACH_DEBUG: - valid = check_plugin_symbol(module, "chrysalide_plugin_attach_debug"); - break; + /* Mémorisation des informations */ - default: - log_variadic_message(LMT_WARNING, - _("Unknown action '0x%02x' in plugin '%s'..."), - interface->actions[i], filename); - break; + if (result) + { + plugin->name = strdup(name); - } + if (desc != NULL) + plugin->desc = strdup(desc); - break; + if (version != NULL) + plugin->version = strdup(version); - case DPS_DISASSEMBLY: - valid = check_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event"); - break; + if (url != NULL) + plugin->url = strdup(url); - case DPS_DETECTION: - valid = check_plugin_symbol(module, "chrysalide_plugin_detect_external_tools"); - break; + if (count > 0) + { + plugin->required = malloc(count * sizeof(char *)); + plugin->required_count = 0; - default: - log_variadic_message(LMT_WARNING, - _("Unknown sub-category '0x%02x' in plugin '%s'..."), sub, filename); + for (i = 0; i < count; i++) + { + for (k = 0; k < plugin->required_count; k++) + if (strcmp(required[i], plugin->required[k]) == 0) break; - } + if (k < plugin->required_count) + continue; -#endif + plugin->required[plugin->required_count++] = strdup(required[i]); - break; + } - default: - log_variadic_message(LMT_WARNING, - _("Unknown category '0x%02x' in plugin '%s'..."), category, filename); - break; + plugin->required = realloc(plugin->required, plugin->required_count * sizeof(char *)); } } - if (!valid) - goto missing_feature; - - gtype = build_dynamic_type(G_TYPE_PLUGIN_MODULE, interface->gtp_name, - (GClassInitFunc)g_plugin_module_init_gclass, module, NULL); - - if (gtype == G_TYPE_INVALID) - goto no_instance; - - result = g_object_new(gtype, NULL); - - result->filename = strdup(filename); - result->module = module; - - result->interface = interface; - - set_self(result); - return result; - no_self_setter: - - log_variadic_message(LMT_ERROR, _("Self pointer setter is missing for plugin '%s'"), filename); - goto bad_plugin; - - no_interface: - - log_variadic_message(LMT_ERROR, _("Main interface is missing for plugin '%s'"), filename); - goto bad_plugin; - - wrong_abi: - - log_variadic_message(LMT_ERROR, _("ABI mismatch detected! Plugin '%s' rejected"), filename); - goto bad_plugin; - - missing_feature: - - log_variadic_message(LMT_ERROR, _("An expected feature is missing for plugin '%s'"), filename); - goto bad_plugin; - - no_instance: - - log_variadic_message(LMT_ERROR, _("Unabled to create an instance of plugin '%s'"), filename); - - bad_plugin: - - g_module_close(module); - - bad_module: - - return NULL; - } /****************************************************************************** * * -* Paramètres : class = classe à initialiser. * -* module = module représentant le greffon chargé en mémoire. * +* Paramètres : plugin = greffon à consulter. * * * -* Description : Initialise la classe des greffons d'extension. * +* Description : Indique le nom associé à un greffon. * * * -* Retour : - * +* Retour : Désignation interne de l'extension, pour référence(s). * * * * Remarques : - * * * ******************************************************************************/ -static void g_plugin_module_init_gclass(GPluginModuleClass *class, GModule *module) +const char *g_plugin_module_get_name(const GPluginModule *plugin) { - const plugin_interface *interface; /* Déclaration d'interfaçage */ - size_t i; /* Boucle de parcours */ - uint32_t action; /* Identifiant d'une action */ - uint32_t category; /* Catégorie principale */ - uint32_t sub; /* Sous-catégorie visée */ - - -#undef load_plugin_symbol - -#define load_plugin_symbol(mod, sym, dest) \ - ({ \ - bool __result; \ - __result = g_module_symbol(mod, sym, (gpointer *)dest); \ - assert(__result); \ - __result; \ - }) - - - load_plugin_symbol(module, "_chrysalide_plugin", &interface); - - for (i = 0; i < interface->actions_count; i++) - { - action = interface->actions[i]; - category = MASK_PLUGIN_CATEGORY(action); - sub = MASK_PLUGIN_SUB_CATEGORY(action); - - switch (category) - { - case DPC_BASIC: - - switch (sub) - { - case DPS_NONE: - break; - - case DPS_PG_MANAGEMENT: - - switch (action) - { - case PGA_PLUGIN_INIT: - load_plugin_symbol(module, "chrysalide_plugin_init", &class->init); - break; - - case PGA_PLUGIN_LOADED: - load_plugin_symbol(module, "chrysalide_plugin_manage", &class->manage); - break; - - case PGA_PLUGIN_EXIT: - load_plugin_symbol(module, "chrysalide_plugin_exit", &class->exit); - break; - - default: - assert(false); - break; - - } - - break; - - case DPS_CORE_MANAGEMENT: - - switch (action) - { - case PGA_NATIVE_PLUGINS_LOADED: - case PGA_ALL_PLUGINS_LOADED: - load_plugin_symbol(module, "chrysalide_plugin_on_plugins_loaded", - &class->plugins_loaded); - break; - - case PGA_TYPE_BUILDING: - load_plugin_symbol(module, "chrysalide_plugin_build_type_instance", - &class->build_instance); - break; - - default: - assert(false); - break; - - } - - break; - - default: - assert(false); - break; - - } - - break; -#if 0 - case DPC_GUI: - - switch (sub) - { - case DPS_SETUP: - - switch (action) - { - case PGA_GUI_THEME: -#ifdef INCLUDE_GTK_SUPPORT - load_plugin_symbol(module, "chrysalide_plugin_include_theme", - &class->include_theme); -#endif - break; - - default: - assert(false); - break; - - } - - break; - - case DPS_RUNNING: - - switch (action) - { - case PGA_PANEL_CREATION: -#ifdef INCLUDE_GTK_SUPPORT - load_plugin_symbol(module, "chrysalide_plugin_on_panel_creation", - &class->notify_panel); -#endif - break; - - case PGA_PANEL_DOCKING: -#ifdef INCLUDE_GTK_SUPPORT - load_plugin_symbol(module, "chrysalide_plugin_on_panel_docking", - &class->notify_docking); -#endif - break; - - default: - assert(false); - break; - - } - - break; + const char *result; /* Valeur finale à renvoyer */ - default: - assert(false); - break; - - } - - break; - - case DPC_BINARY_PROCESSING: - - switch (sub) - { - case DPS_CONTENT: - - switch (action) - { - case PGA_CONTENT_EXPLORER: - case PGA_CONTENT_RESOLVER: - load_plugin_symbol(module, "chrysalide_plugin_handle_binary_content", - &class->handle_content); - break; - - case PGA_CONTENT_ANALYZED: - load_plugin_symbol(module, "chrysalide_plugin_handle_loaded_content", - &class->handle_loaded); - break; - - default: - assert(false); - break; - - } - - break; - - case DPS_FORMAT: + result = plugin->name; - switch (action) - { - case PGA_FORMAT_ANALYSIS_STARTED: - case PGA_FORMAT_ANALYSIS_ENDED: - case PGA_FORMAT_POST_ANALYSIS_STARTED: - case PGA_FORMAT_POST_ANALYSIS_ENDED: - load_plugin_symbol(module, "chrysalide_plugin_handle_binary_format_analysis", - &class->handle_fmt_analysis); - break; - - case PGA_FORMAT_PRELOAD: - load_plugin_symbol(module, "chrysalide_plugin_preload_binary_format", &class->preload_format); - break; - - case PGA_FORMAT_ATTACH_DEBUG: - load_plugin_symbol(module, "chrysalide_plugin_attach_debug", &class->attach_debug); - break; + return result; - default: - assert(false); - break; +} - } - break; +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Fournit une description fonctionnelle d'un greffon. * +* * +* Retour : Description textuelle associée à une extension ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ - case DPS_DISASSEMBLY: - load_plugin_symbol(module, "chrysalide_plugin_process_disassembly_event", &class->process_disass); - break; +const char *g_plugin_module_get_desc(const GPluginModule *plugin) +{ + const char *result; /* Valeur finale à renvoyer */ - case DPS_DETECTION: - load_plugin_symbol(module, "chrysalide_plugin_detect_external_tools", &class->detect); - break; + result = plugin->desc; - default: - assert(false); - break; + return result; - } +} -#endif - break; +/****************************************************************************** +* * +* Paramètres : plugin = greffon à consulter. * +* * +* Description : Fournit la version d'un greffon et de ses fonctionnalités. * +* * +* Retour : Version sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ - default: - assert(false); - break; +const char *g_plugin_module_get_version(const GPluginModule *plugin) +{ + const char *result; /* Valeur finale à renvoyer */ - } + result = plugin->version; - } + return result; } /****************************************************************************** * * -* Paramètres : plugin = greffon à valider. * +* Paramètres : plugin = greffon à consulter. * * * -* Description : Fournit le nom brut associé au greffon. * +* Description : Fournit l'URL des ressources en ligne liées à un greffon. * * * -* Retour : Désignation brute du greffon. * +* Retour : URL de renvoi associée à une extension ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -char *g_plugin_module_get_modname(const GPluginModule *plugin) +const char *g_plugin_module_get_url(const GPluginModule *plugin) { - char *result; /* Désignation brute à renvoyer*/ - GPluginModuleClass *class; /* Classe de l'instance active */ - - class = G_PLUGIN_MODULE_GET_CLASS(plugin); - - result = class->get_modname(plugin); + const char *result; /* Valeur finale à renvoyer */ - /** - * Tente une opération de la dernière chance. - * - * Dans le cas d'un module Python, la fonction de classe peut ne pas - * trouver de support si l'extension Python n'est pas au point. - */ - if (result == NULL && class->get_modname != _g_plugin_module_get_modname) - result = _g_plugin_module_get_modname(plugin); + result = plugin->url; return result; @@ -844,41 +389,24 @@ char *g_plugin_module_get_modname(const GPluginModule *plugin) /****************************************************************************** * * -* Paramètres : plugin = greffon à valider. * +* Paramètres : plugin = greffon à consulter. * +* count = taille de la liste fournie. [OUT] * * * -* Description : Fournit le nom brut associé au greffon. * +* Description : Fournit la liste des dépendances d'un greffon donné. * * * -* Retour : Désignation brute du greffon. * +* Retour : Liste des noms d'extensions requises pour une extension. * * * * Remarques : - * * * ******************************************************************************/ -static char *_g_plugin_module_get_modname(const GPluginModule *plugin) +const char * const *g_plugin_module_get_requirements(const GPluginModule *plugin, size_t *count) { - char *result; /* Désignation brute à renvoyer*/ - char *path; /* Chemin à traiter */ - char *filename; /* Nom de bibliothèque partagée*/ - size_t length; /* Taille du nom */ - - path = strdup(g_plugin_module_get_filename(G_PLUGIN_MODULE(plugin))); - - filename = basename(path); - - if (strncmp(filename, "lib", 3) == 0) - filename += 3; - - length = strlen(filename); - - if (length >= 3) - { - if (strncmp(&filename[length - 3], ".so", 3) == 0) - filename[length - 3] = '\0'; - } + const char * const *result; /* Valeur finale à renvoyer */ - result = strdup(filename); + result = CONST_ARRAY_CAST(plugin->required, char); - free(path); + *count = plugin->required_count; return result; @@ -889,7 +417,7 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin) * * * Paramètres : plugin = greffon à consulter. * * * -* Description : Indique le fichier contenant le greffon manipulé. * +* Description : Pointe le fichier contenant le greffon manipulé. * * * * Retour : Chemin d'accès au greffon. * * * @@ -897,28 +425,42 @@ static char *_g_plugin_module_get_modname(const GPluginModule *plugin) * * ******************************************************************************/ -const char *g_plugin_module_get_filename(const GPluginModule *plugin) +char *g_plugin_module_get_filename(const GPluginModule *plugin) { - return plugin->filename; + char *result; /* Chemin d'accès à renvoyer */ + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + result = class->get_filename(plugin); + + return result; } /****************************************************************************** * * -* Paramètres : plugin = greffon à consulter. * +* Paramètres : plugin = greffon à valider. * * * -* Description : Fournit la description du greffon dans son intégralité. * +* Description : Fournit le nom brut associé au greffon. * * * -* Retour : Interfaçage renseigné. * +* Retour : Désignation brute du greffon. * * * * Remarques : - * * * ******************************************************************************/ -const plugin_interface *g_plugin_module_get_interface(const GPluginModule *plugin) +char *g_plugin_module_get_modname(const GPluginModule *plugin) { - return plugin->interface; + char *result; /* Désignation brute à renvoyer*/ + GPluginModuleClass *class; /* Classe de l'instance active */ + + class = G_PLUGIN_MODULE_GET_CLASS(plugin); + + result = class->get_modname(plugin); + + return result; } @@ -979,7 +521,6 @@ void g_plugin_module_override_flags(GPluginModule *plugin, PluginStatusFlags fla bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule **list, size_t count) { bool result; /* Bilan à faire remonter */ - const plugin_interface *pg_iface; /* Définition du greffon */ bitfield_t *new; /* Nouvelle définition */ size_t i; /* Boucle de parcours */ GPluginModule *dependency; /* Module nécessaire */ @@ -997,15 +538,13 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule * if ((plugin->flags & (PSF_UNKNOW_DEP | PSF_DEP_LOOP)) == 0) { - pg_iface = g_plugin_module_get_interface(plugin); - /* Collecte des dépendances */ new = dup_bit_field(plugin->dependencies); - for (i = 0; i < pg_iface->required_count; i++) + for (i = 0; i < plugin->required_count; i++) { - dependency = get_plugin_by_name(pg_iface->required[i], &index); + dependency = get_plugin_by_name(plugin->required[i], &index); if (dependency == NULL) plugin->flags |= PSF_UNKNOW_DEP; @@ -1023,7 +562,7 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule * */ if (test_in_bit_field(plugin->dependencies, index)) - g_object_unref(G_OBJECT(dependency)); + unref_object(dependency); } @@ -1041,13 +580,14 @@ bool g_plugin_module_resolve_dependencies(GPluginModule *plugin, GPluginModule * /* Vérification sanitaire */ - dependency = get_plugin_by_name(pg_iface->name, &index); + dependency = get_plugin_by_name(plugin->name, &index); assert(dependency != NULL); + assert(dependency == plugin); if (test_in_bit_field(plugin->dependencies, index)) plugin->flags |= PSF_DEP_LOOP; - g_object_unref(G_OBJECT(dependency)); + unref_object(dependency); } @@ -1075,12 +615,12 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co { bool result; /* Bilan à retourner */ PluginStatusFlags flags; /* Fanions de greffon */ - const plugin_interface *pg_iface; /* Définition du greffon */ size_t i; /* Boucle de parcours */ GPluginModule *dependency; /* Module nécessaire */ + char *filename; /* Chemin d'accès au greffon */ GPluginModuleClass *class; /* Classe de l'instance active */ - //GGenConfig *config; /* Configuration à charger */ - char *dir; /* Répertoire modifiable */ + char *tmp; /* Chaîne modifiable */ + char *dir; /* Pointeur vers répertoire */ /* Si un essai précédent a déjà échoué ou réussi... */ @@ -1092,40 +632,41 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co /* Chargement des dépendances */ - pg_iface = g_plugin_module_get_interface(plugin); - result = true; - for (i = 0; i < pg_iface->required_count && result; i++) + filename = g_plugin_module_get_filename(plugin); + + for (i = 0; i < plugin->required_count && result; i++) { - dependency = get_plugin_by_name(pg_iface->required[i], NULL); + dependency = get_plugin_by_name(plugin->required[i], NULL); assert(dependency != NULL); result = g_plugin_module_load(dependency, list, count); - g_object_unref(G_OBJECT(dependency)); + unref_object(dependency); } if (!result) { - log_variadic_message(LMT_ERROR, - _("Some dependencies failed to load for plugin '%s'"), plugin->filename); + log_variadic_message(LMT_ERROR, _("Some dependencies failed to load for plugin '%s'"), filename); + + plugin->flags |= PSF_FAILURE; goto failure; + } /* Chargement du greffon courant */ class = G_PLUGIN_MODULE_GET_CLASS(plugin); - if (class->init != NULL) + if (class->enable != NULL) { - result = class->init(plugin); + result = class->enable(plugin); if (!result) { - log_variadic_message(LMT_ERROR, - _("Plugin '%s' failed to load itself..."), plugin->filename); + log_variadic_message(LMT_ERROR, _("Plugin '%s' failed to load itself..."), filename); plugin->flags |= PSF_FAILURE; goto failure; @@ -1134,39 +675,23 @@ bool g_plugin_module_load(GPluginModule *plugin, GPluginModule **list, size_t co } - g_plugin_module_create_config(plugin); - - result = g_plugin_module_manage(plugin, PGA_PLUGIN_LOADED); + /* Message de bilan */ - if (!result) - { - log_variadic_message(LMT_ERROR, - _("Plugin '%s' failed to complete loading..."), plugin->filename); - - plugin->flags |= PSF_FAILURE; - goto failure; - - } - - /* - config = g_plugin_module_get_config(plugin); - g_generic_config_read(config); - g_object_unref(G_OBJECT(config)); - */ - - dir = strdup(plugin->filename); - dir = dirname(dir); + tmp = strdup(filename); + dir = dirname(tmp); log_variadic_message(LMT_PROCESS, _("Loaded the '<b>%s</b>' file as plugin from the '<b>%s</b>' directory"), - strrchr(plugin->filename, G_DIR_SEPARATOR) + 1, dir); + strrchr(filename, G_DIR_SEPARATOR) + 1, dir); - free(dir); + free(tmp); plugin->flags |= PSF_LOADED; failure: + free(filename); + return result; } @@ -1227,31 +752,6 @@ char *g_plugin_module_build_config_filename(const GPluginModule *plugin, const c /****************************************************************************** * * -* Paramètres : plugin = greffon à compléter. * -* * -* Description : Met en place la configuration dédiée au greffon. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_plugin_module_create_config(GPluginModule *plugin) -{ - char *filename; /* Chemin d'accès particulier */ - - filename = g_plugin_module_build_config_filename(plugin, "config.xml", false); - - //plugin->config = g_generic_config_new_from_file(filename); - - free(filename); - -} - - -/****************************************************************************** -* * * Paramètres : plugin = greffon à consulter. * * * * Description : Fournit la configuration mise en place pour le greffon. * @@ -1295,11 +795,11 @@ void g_plugin_module_log_simple_message(const GPluginModule *plugin, LogMessageT size_t len; /* Taille tampon disponible */ char *buffer; /* Tampon du msg reconstitué */ - len = 4 + strlen(plugin->interface->name) + 6 + strlen(msg) + 1; + len = 4 + strlen(plugin->name) + 6 + strlen(msg) + 1; buffer = calloc(len, sizeof(char)); strcpy(buffer, "<i>["); - strcat(buffer, plugin->interface->name); + strcat(buffer, plugin->name); strcat(buffer, "]</i> "); strcat(buffer, msg); @@ -1345,80 +845,12 @@ void g_plugin_module_log_variadic_message(const GPluginModule *plugin, LogMessag } -/****************************************************************************** -* * -* Paramètres : plugin = greffon à manipuler. * -* action = type d'action attendue. * -* * -* Description : Encadre une étape de la vie d'un greffon. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_plugin_module_manage(GPluginModule *plugin, PluginAction action) -{ - bool result; /* Bilan à faire remonter */ - GPluginModuleClass *class; /* Classe de l'instance active */ - const plugin_interface *pg_iface; /* Informations à consulter */ - size_t i; /* Boucle de parcours */ - bool handle_action; /* Action supportée ? */ - - class = G_PLUGIN_MODULE_GET_CLASS(plugin); - - if (class->manage == NULL) - result = true; - - else - { - handle_action = false; - - pg_iface = g_plugin_module_get_interface(plugin); - - for (i = 0; i < pg_iface->actions_count; i++) - if (pg_iface->actions[i] == PGA_PLUGIN_LOADED) - { - handle_action = true; - break; - } - - if (handle_action) - result = class->manage(plugin/*, action*/); - else - result = true; - - } - - return result; - -} -/****************************************************************************** -* * -* Paramètres : plugin = greffon à manipuler. * -* action = type d'action attendue. * -* unused = variable non utilisé pour l'usage de __VA_ARGS__. * -* * -* Description : Accompagne la fin du chargement des modules. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_plugin_module_notify_plugins_loaded(GPluginModule *plugin, PluginAction action, void *unused) -{ - GPluginModuleClass *class; /* Classe de l'instance active */ - class = G_PLUGIN_MODULE_GET_CLASS(plugin); - class->plugins_loaded(plugin, action); -} +#if 0 /****************************************************************************** @@ -1450,8 +882,6 @@ gpointer g_plugin_module_build_type_instance(GPluginModule *plugin, PluginAction -#if 0 - #ifdef INCLUDE_GTK_SUPPORT diff --git a/src/plugins/plugin.h b/src/plugins/plugin.h index 5c473b2..a4cc388 100644 --- a/src/plugins/plugin.h +++ b/src/plugins/plugin.h @@ -52,6 +52,27 @@ DECLARE_GTYPE(GPluginModule, g_plugin_module, G, PLUGIN_MODULE); +/* Indique le nom associé à un greffon. */ +const char *g_plugin_module_get_name(const GPluginModule *); + +/* Fournit une description fonctionnelle d'un greffon. */ +const char *g_plugin_module_get_desc(const GPluginModule *); + +/* Fournit la version d'un greffon et de ses fonctionnalités. */ +const char *g_plugin_module_get_version(const GPluginModule *); + +/* Fournit l'URL des ressources en ligne liées à un greffon. */ +const char *g_plugin_module_get_url(const GPluginModule *); + +/* Fournit la liste des dépendances d'un greffon donné. */ +const char * const *g_plugin_module_get_requirements(const GPluginModule *, size_t *); + +/* Pointe le fichier contenant le greffon manipulé. */ +char *g_plugin_module_get_filename(const GPluginModule *); + +/* Fournit le nom brut associé au greffon. */ +char *g_plugin_module_get_modname(const GPluginModule *); + /* Fanions indiquant le statut du greffon */ typedef enum _PluginStatusFlags { @@ -66,19 +87,6 @@ typedef enum _PluginStatusFlags #define BROKEN_PLUGIN_STATUS (PSF_UNKNOW_DEP | PSF_DEP_LOOP | PSF_FAILURE) - -/* Crée un module pour un greffon donné. */ -GPluginModule *g_plugin_module_new(const gchar *); - -/* Fournit le nom brut associé au greffon. */ -char *g_plugin_module_get_modname(const GPluginModule *); - -/* Indique le fichier contenant le greffon manipulé. */ -const char *g_plugin_module_get_filename(const GPluginModule *); - -/* Fournit la description du greffon dans son intégralité. */ -const plugin_interface *g_plugin_module_get_interface(const GPluginModule *); - /* Fournit des indications sur l'état du greffon. */ PluginStatusFlags g_plugin_module_get_flags(const GPluginModule *); @@ -103,17 +111,12 @@ void g_plugin_module_log_simple_message(const GPluginModule *, LogMessageType, c /* Présente dans le journal un message complexe. */ void g_plugin_module_log_variadic_message(const GPluginModule *, LogMessageType, const char *, ...); -/* Encadre une étape de la vie d'un greffon. */ -bool g_plugin_module_manage(GPluginModule *, PluginAction); -/* Accompagne la fin du chargement des modules natifs. */ -void g_plugin_module_notify_plugins_loaded(GPluginModule *, PluginAction, void *); +#if 0 /* Crée une instance à partir d'un type dynamique externe. */ gpointer g_plugin_module_build_type_instance(GPluginModule *, PluginAction, GType); -#if 0 - #ifdef INCLUDE_GTK_SUPPORT /* Complète une liste de resources pour thème. */ diff --git a/src/plugins/self.h b/src/plugins/self.h index 4d5ddb0..78a3fe6 100644 --- a/src/plugins/self.h +++ b/src/plugins/self.h @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * self.h - définitions pour inclusion dans les différents greffons + * self.h - définitions de fonctionnalités facilitant la mise en place d'extensions natives * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -26,72 +26,55 @@ #define _PLUGINS_SELF_H -#ifndef _PLUGINS_PLUGIN_H -# include "plugin.h" -#endif +#include <assert.h> +#include <malloc.h> + + +#include "plugin.h" #include "../common/compiler.h" -/* Facilitations de déclarations */ +/* Symboles principaux */ + +#define PLUGIN_CORE_SELF \ +static GPluginModule *_this_plugin = NULL; \ +static void chrysalide_plugin_set_self(GPluginModule *); \ +static void chrysalide_plugin_set_self(GPluginModule *plugin) \ +{ \ + assert(_this_plugin == NULL); \ + _this_plugin = plugin; \ +}; \ +__private GPluginModule *_chrysalide_plugin_get_self(void); \ +__private GPluginModule *_chrysalide_plugin_get_self(void) \ +{ \ + return _this_plugin; \ +}; + +#define NATIVE_PLUGIN_ENTRYPOINT(fc) \ +PLUGIN_CORE_SELF; \ +G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *); \ +G_MODULE_EXPORT GPluginModule *get_chrysalide_plugin_instance(GModule *module) \ +{ \ + GPluginModule *result; /* Instance à retourner */ \ + result = fc(module); \ + chrysalide_plugin_set_self(result); \ + return result; \ +} + + +/* Spécifications */ #define CHRYSALIDE_WEBSITE(p) "https://www.chrysalide.re/" p -#define EMPTY_PG_LIST(name) \ - name = NULL, \ - name ## _count = 0 \ - -#define BUILD_PG_LIST(name, lst) \ - name = lst, \ - name ## _count = sizeof(lst) / sizeof(lst[0]) \ - -#define AL(...) BUILD_PG_LIST(.actions, ((plugin_action_t []){ __VA_ARGS__ })) - -#define RL(...) BUILD_PG_LIST(.required, ((char *[]){ __VA_ARGS__ })) - -#define NO_REQ EMPTY_PG_LIST(.required) - - -/* Composants d'interface */ - -#define PLUGIN_CORE_SELF \ -static GPluginModule *_this_plugin = NULL; \ -G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p); \ -G_MODULE_EXPORT void chrysalide_plugin_set_self(GPluginModule *p) { _this_plugin = p; }; \ -__private GPluginModule *_chrysalide_plugin_get_self(void); \ -__private GPluginModule *_chrysalide_plugin_get_self(void) { return _this_plugin; }; - -#define PLUGIN_CORE_PROPS(n, d, v, u, c) \ - \ - .magic = CHRYSALIDE_PLUGIN_MAGIC, \ - .abi_version = CURRENT_ABI_VERSION, \ - \ - .gtp_name = "G" n "Plugin", \ - .name = n, \ - .desc = d, \ - .version = v, \ - .url = u, \ - \ - .container = c - -#define DEFINE_CHRYSALIDE_PLUGIN(n, d, v, u, r, a) \ -PLUGIN_CORE_SELF \ -G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \ - PLUGIN_CORE_PROPS(n, d, v, u, false), \ - r, \ - a, \ -} +#define NO_REQ NULL, 0 -#define DEFINE_CHRYSALIDE_CONTAINER_PLUGIN(n, d, v, u, r, a) \ -PLUGIN_CORE_SELF \ -G_MODULE_EXPORT const plugin_interface _chrysalide_plugin = { \ - PLUGIN_CORE_PROPS(n, d, v, u, true), \ - r, \ - a, \ -} +#define BUILD_PG_LIST(lst) lst, sizeof(lst) / sizeof(lst[0]) + +#define REQ_LIST(...) BUILD_PG_LIST((const char *[]){ __VA_ARGS__ }) -/* Manipulations accélérées */ +/* Journalisation */ __private GPluginModule *_chrysalide_plugin_get_self(void); |