/* Chrysalide - Outil d'analyse de fichiers binaires * pglist.c - gestion de l'ensemble des greffons * * Copyright (C) 2009-2017 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 "pglist.h" #include #include #include #include #include #include "plugin-int.h" #include "../common/extstr.h" /* Représentation dédiée aux listes de greffons */ typedef struct _pg_array { PluginAction action; /* Action commune ou PGA_ALL */ GPluginModule **plugins; /* Liste de greffons */ size_t plugins_count; /* Taille de cette liste */ } pg_array; /* Propriétés de l'ensemble des greffons */ typedef struct _plugins_list { GObject *ref; /* Référencement global */ pg_array *all; /* Liste de tous les greffons */ pg_array sorted[PGA_COUNT]; /* Tri par catégories */ } plugins_list; /* Liste de l'ensemble des greffons */ static plugins_list _list; /* Filtre les répertoire et les modules de greffons pootentels. */ int filter_dirs_or_mods(const struct dirent *); /* Part à la recherche de greffons sous forme de modules. */ void browse_directory_for_plugins(plugins_list *, const char *); /****************************************************************************** * * * Paramètres : ref = espace de référencement global. * * * * Description : Procède au chargement des différents greffons trouvés. * * * * Retour : Toujours true (même s'il y a des erreurs de chargement). * * * * Remarques : - * * * ******************************************************************************/ bool init_all_plugins(GObject *ref) { size_t i; /* Boucle de parcours */ _list.ref = ref; g_object_ref(ref); for (i = 0; i < PGA_COUNT; i++) _list.sorted[i].action = PGA_EMPTY; _list.sorted[0].action = PGA_ALL; _list.all = &_list.sorted[0]; browse_directory_for_plugins(&_list, PACKAGE_SOURCE_DIR "/plugins"); return true; } /****************************************************************************** * * * Paramètres : - * * * * Description : Procède au déchargement des différents greffons présents. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void exit_all_plugins(void) { size_t i; /* Boucle de parcours */ for (i = 0; i < _list.all->plugins_count; i++) g_object_unref(_list.all->plugins[i]); for (i = 0; i < PGA_COUNT; i++) free(_list.sorted[i].plugins); g_object_unref(_list.ref); } /****************************************************************************** * * * Paramètres : entry = entrée de répertoire à analyser. * * * * Description : Filtre les répertoire et les modules de greffons pootentels. * * * * Retour : Valeur non nulle pour garder l'élément. * * * * Remarques : - * * * ******************************************************************************/ int filter_dirs_or_mods(const struct dirent *entry) { int result; /* Conclusion à remonter */ if (entry->d_type == DT_DIR) result = strcmp(entry->d_name, ".") * strcmp(entry->d_name, ".."); else result = (strrcmp(entry->d_name, "." G_MODULE_SUFFIX) == 0 ? 1 : 0); return result; } /****************************************************************************** * * * Paramètres : list = liste de greffons à compléter si possible. * * dir = répertoire à parcourir en quête de greffons (sans /). * * * * Description : Part à la recherche de greffons sous forme de modules. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void browse_directory_for_plugins(plugins_list *list, const char *dir) { struct dirent **namelist; /* Eléments trouvés */ int ret; /* Bilan du parcours */ char *filename; /* Elément à ausculter */ GPluginModule *plugin; /* Greffon à intégrer ou pas */ ret = scandir(dir, &namelist, filter_dirs_or_mods, alphasort); if (ret < 0) { perror("scandir"); return; } while (ret--) { filename = (char *)calloc(strlen(dir) + 1 + strlen(namelist[ret]->d_name) + 1, sizeof(char)); strcpy(filename, dir); strcat(filename, G_DIR_SEPARATOR_S); strcat(filename, namelist[ret]->d_name); if (namelist[ret]->d_type == DT_DIR) browse_directory_for_plugins(list, filename); else { plugin = g_plugin_module_new(filename, _list.ref); if (plugin != NULL) add_plugin_to_main_list(plugin); } free(filename); free(namelist[ret]); } free(namelist); } /****************************************************************************** * * * Paramètres : action = fonctionnalité recherchée. * * count = nombre de greffons trouvés. [OUT] * * * * Description : Founit les greffons offrant le service demandé. * * * * Retour : Liste de greffons correspondants issue d'un tri interne. * * * * Remarques : - * * * ******************************************************************************/ const GPluginModule **get_all_plugins_for_action(PluginAction action, size_t *count) { const GPluginModule **result; /* Greffon à retourner */ size_t i; /* Boucle de parcours */ result = NULL; *count = 0; for (i = 0; i < PGA_COUNT; i++) if (_list.sorted[i].action == action) { result = (const GPluginModule **)_list.sorted[i].plugins; *count = _list.sorted[i].plugins_count; break; } return result; } /****************************************************************************** * * * Paramètres : plugin = greffon à ajouter aux autres disponibles. * * * * Description : Ajoute un greffon à la liste principale de greffons. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void add_plugin_to_main_list(GPluginModule *plugin) { const plugin_interface *interface; /* Informations à consulter */ size_t i; /* Boucle de parcours #1 */ size_t j; /* Boucle de parcours #2 */ interface = g_plugin_module_get_interface(plugin); void add_plugin_into_array(pg_array *array, GPluginModule *pg) { array->plugins = (GPluginModule **)realloc(array->plugins, ++array->plugins_count * sizeof(GPluginModule)); array->plugins[array->plugins_count - 1] = pg; } /* FIXME : lock */ add_plugin_into_array(_list.all, plugin); for (i = 0; i < interface->actions_count; i++) { if (interface->actions[i] == PGA_ALL) continue; for (j = 1; j < PGA_COUNT; j++) { if (_list.sorted[j].action == interface->actions[i]) { add_plugin_into_array(&_list.sorted[j], plugin); break; } else if (_list.sorted[j].action == PGA_EMPTY) { add_plugin_into_array(&_list.sorted[j], plugin); _list.sorted[j].action = interface->actions[i]; break; } } assert(j < PGA_COUNT); } /* FIXME : lock */ }