diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2014-07-10 14:47:37 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2014-07-10 14:47:37 (GMT) |
commit | db863244b804cbf4c06399f7c6f8241d91c9ee9b (patch) | |
tree | da7cc911b0f10c5122536271235ab68f2202804a /src/glibext | |
parent | e8aa314462196cc9e8461ae23eb13f8bffcc983f (diff) |
Fully rewritten the core configuration system.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@381 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/Makefile.am | 1 | ||||
-rw-r--r-- | src/glibext/configuration.c | 1232 | ||||
-rw-r--r-- | src/glibext/configuration.h | 199 | ||||
-rw-r--r-- | src/glibext/gbuffersegment.c | 2 |
4 files changed, 1433 insertions, 1 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 19ff59a..50b9902 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -5,6 +5,7 @@ noinst_LTLIBRARIES = libglibext.la libglibext_la_SOURCES = \ chrysamarshal.h chrysamarshal.c \ + configuration.h configuration.c \ delayed-int.h \ delayed.h delayed.c \ gbinportion.h gbinportion.c \ diff --git a/src/glibext/configuration.c b/src/glibext/configuration.c new file mode 100644 index 0000000..30cbcaf --- /dev/null +++ b/src/glibext/configuration.c @@ -0,0 +1,1232 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * configuration.c - éléments de configuration du programme + * + * Copyright (C) 2009-2014 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 "configuration.h" + + +#include <assert.h> +#include <limits.h> +#include <malloc.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + + +#include "../common/cpp.h" +#include "../common/extstr.h" +#include "../common/fnv1a.h" +#include "../common/io.h" +#include "../common/xdg.h" +#include "../common/xml.h" + + + +/* ---------------------------- ELEMENT DE CONFIGURATION ---------------------------- */ + + +/* Valeurs supportées par les paramètres */ +typedef union _param_value +{ + bool boolean; /* Valeur booléenne */ + int integer; /* Valeur entière */ + char *string; /* Chaîne de caractères */ + +} param_value; + +/* Configuration générique quelconque (instance) */ +struct _GCfgParam +{ + GObject parent; /* A laisser en premier */ + + char *path; /* Chemin d'accès XML */ + fnv64_t hash; /* Empreinte pour accès rapide */ + + ConfigParamType type; /* Type de valeur */ + + ConfigParamState cached_state; /* Etat du paramétrage */ + + param_value def; /* Valeur par défaut */ + bool def_empty; /* Non défini par défaut ? */ + param_value cur; /* Valeur courante */ + bool cur_empty; /* Actuellement non défini ? */ + +}; + +/* Configuration générique quelconque (classe) */ +struct _GCfgParamClass +{ + GObjectClass parent; /* A laisser en premier */ + + /* Signaux */ + + void (*modified) (GCfgParam *); + +}; + + +/* Initialise la classe des blocs de données binaires. */ +static void g_config_param_class_init(GCfgParamClass *); + +/* Initialise une instance de bloc de données binaires. */ +static void g_config_param_init(GCfgParam *); + +/* Supprime toutes les références externes. */ +static void g_config_param_dispose(GCfgParam *); + +/* Procède à la libération totale de la mémoire. */ +static void g_config_param_finalize(GCfgParam *); + +/* Lit un paramètre de configuration depuis un fichier. */ +static bool g_config_param_read(GCfgParam *, xmlXPathContextPtr); + +/* Ecrit un paramètre de configuration dans un fichier. */ +static bool g_config_param_write(GCfgParam *, xmlDocPtr, xmlXPathContextPtr); + + + +/* ----------------------- GESTION GENERIQUE DE CONFIGURATION ----------------------- */ + + +/* Configuration générique quelconque (instance) */ +struct _GGenConfig +{ + GObject parent; /* A laisser en premier */ + + char *filename; /* CHemin d'accès complet */ + + GList *params; /* Eléments de configuration */ + GRWLock params_access; /* Verrou de protection */ + +}; + +/* Configuration générique quelconque (classe) */ +struct _GGenConfigClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + +/* Initialise la classe des blocs de données binaires. */ +static void g_generic_config_class_init(GGenConfigClass *); + +/* Initialise une instance de bloc de données binaires. */ +static void g_generic_config_init(GGenConfig *); + +/* Supprime toutes les références externes. */ +static void g_generic_config_dispose(GGenConfig *); + +/* Procède à la libération totale de la mémoire. */ +static void g_generic_config_finalize(GGenConfig *); + + + +/* ---------------------------------------------------------------------------------- */ +/* ELEMENT DE CONFIGURATION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour les configurations géénriques. */ +G_DEFINE_TYPE(GCfgParam, g_config_param, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des blocs de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_config_param_class_init(GCfgParamClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_config_param_dispose; + object->finalize = (GObjectFinalizeFunc)g_config_param_finalize; + + g_signal_new("modified", + G_TYPE_CFG_PARAM, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GCfgParamClass, modified), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + +} + + +/****************************************************************************** +* * +* Paramètres : param = instance à initialiser. * +* * +* Description : Initialise une instance de bloc de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_config_param_init(GCfgParam *param) +{ + +} + + +/****************************************************************************** +* * +* Paramètres : param = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_config_param_dispose(GCfgParam *param) +{ + G_OBJECT_CLASS(g_config_param_parent_class)->dispose(G_OBJECT(param)); + +} + + +/****************************************************************************** +* * +* Paramètres : param = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_config_param_finalize(GCfgParam *param) +{ + free(param->path); + + switch (param->type) + { + case CPT_STRING: + if (param->def.string != NULL) + free(param->def.string); + if (param->cur.string != NULL) + free(param->cur.string); + break; + + default: + break; + + } + + G_OBJECT_CLASS(g_config_param_parent_class)->finalize(G_OBJECT(param)); + +} + + +/****************************************************************************** +* * +* Paramètres : path = chemin d'accès à un paramètre en guise de clef. * +* type = type de paramètre à installer. * +* ... = valeur par défaut du paramètre. * +* * +* Description : Crée un paramètre de configuration. * +* * +* Retour : Elément mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCfgParam *g_config_param_new(const char *path, ConfigParamType type, ...) +{ + GCfgParam *result; /* Structure à retourner */ + va_list ap; /* Liste d'arguments */ + + result = g_object_new(G_TYPE_CFG_PARAM, NULL); + + result->path = strdup(path); + result->hash = fnv_64a_hash(path); + + result->type = type; + + va_start(ap, type); + + switch (result->type) + { + case CPT_BOOLEAN: + result->def.boolean = va_arg(ap, /*bool*/int); + break; + + case CPT_INTEGER: + result->def.integer = va_arg(ap, int); + break; + + case CPT_STRING: + result->def.string = va_arg(ap, char *); + if (result->def.string != NULL) + result->def.string = strdup(result->def.string); + break; + + default: + g_object_unref(G_OBJECT(result)); + result = NULL; + assert(false); + break; + + } + + va_end(ap); + + g_config_param_reset(result); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : path = chemin d'accès à un paramètre en guise de clef. * +* type = type de paramètre à installer. * +* * +* Description : Crée un paramètre de configuration sans valeur. * +* * +* Retour : Elément mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCfgParam *g_config_param_new_empty(const char *path, ConfigParamType type) +{ + GCfgParam *result; /* Structure à retourner */ + + result = g_object_new(G_TYPE_CFG_PARAM, NULL); + + result->path = strdup(path); + result->hash = fnv_64a_hash(path); + + result->type = type; + + g_config_param_make_empty(result); + + result->def = result->cur; + result->def_empty = true; + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : config = paramètre de configuration à charger. * +* context = contexte de lecture d'un fichier XML. * +* * +* Description : Lit un paramètre de configuration depuis un fichier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_config_param_read(GCfgParam *param, xmlXPathContextPtr context) +{ + char *access; /* Chemin d'accès XML */ + char *value; /* Valeur en chaîne de carac. */ + + access = strdup(param->path); + access = strrpl(access, ".", "/"); + access = strprep(access, "/ChrysalideConfig/"); + + value = get_node_text_value(context, access); + if (value == NULL) goto gcpr_no_value; + + if (strlen(value) == 0) + g_config_param_make_empty(param); + + else + switch (param->type) + { + case CPT_BOOLEAN: + g_config_param_set_value(param, strcmp(value, "true") == 0); + break; + + case CPT_INTEGER: + g_config_param_set_value(param, atoi(value)); + break; + + case CPT_STRING: + g_config_param_set_value(param, value); + break; + + default: + assert(false); + break; + + } + + free(value); + + gcpr_no_value: + + free(access); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : config = paramètre de configuration à charger. * +* xdoc = document XML à mettre en place. * +* context = contexte de lecture d'un fichier XML. * +* * +* Description : Ecrit un paramètre de configuration dans un fichier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static bool g_config_param_write(GCfgParam *param, xmlDocPtr xdoc, xmlXPathContextPtr context) +{ + bool result; /* Bilan à retourner */ + ConfigParamState state; /* Etat du paramètre */ + char *access; /* Chemin d'accès XML */ + char int_val[sizeof(XSTR(INT_MIN)) + 1];/* Valeur en chaîne de carac. */ + + state = g_config_param_get_state(param); + + if (state & CPS_DEFAULT) + return true; + + result = true; + + access = strdup(param->path); + access = strrpl(access, ".", "/"); + access = strprep(access, "/ChrysalideConfig/"); + + if (state & CPS_EMPTY) + result = add_content_to_node(xdoc, context, access, ""); + + else + switch (param->type) + { + case CPT_BOOLEAN: + result = add_content_to_node(xdoc, context, access, + param->cur.boolean ? "true" : "false"); + break; + + case CPT_INTEGER: + snprintf(int_val, sizeof(int_val), "%d", param->cur.integer); + result = add_content_to_node(xdoc, context, access, int_val); + break; + + case CPT_STRING: + + if (param->def.string != NULL && param->def.string != NULL + && strcmp(param->cur.string, param->def.string) == 0) + break; + + result = add_content_to_node(xdoc, context, access, + param->cur.string != NULL ? param->cur.string : ""); + break; + + default: + assert(false); + break; + + } + + free(access); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre de configuration à analyser. * +* path = chemin d'accès à retrouver. * +* * +* Description : Etablit une comparaison selon un chemin d'accès. * +* * +* Retour : -1, 0 ou 1 selon les conclusions de la comparaison. * +* * +* Remarques : - * +* * +******************************************************************************/ + +gint g_config_param_compare(const GCfgParam *param, const GCfgParam *path) +{ + gint result; /* Bilan à renvoyer */ + + result = cmp_fnv_64a(param->hash, path->hash); + + if (result == 0) + result = strcmp(param->path, path->path); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre de configuration à consulter. * +* * +* Description : Indique le chemin d'accès utilisé pour un paramètre. * +* * +* Retour : Clef servant de chemin d'accès. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_config_param_get_path(const GCfgParam *param) +{ + return param->path; + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre de configuration à consulter. * +* * +* Description : Indique le type de valeur utilisée par un paramètre. * +* * +* Retour : Type de paramètre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ConfigParamType g_config_param_get_ptype(const GCfgParam *param) +{ + return param->type; + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre de configuration à consulter. * +* * +* Description : Indique le statut d'une valeur utilisée par un paramètre. * +* * +* Retour : Etat de paramètre. * +* * +* Remarques : - * +* * +******************************************************************************/ + +ConfigParamState g_config_param_get_state(GCfgParam *param) +{ + if (param->cached_state == CPS_UNDEFINED) + { + if (param->def_empty || param->cur_empty) + { + param->cached_state = (param->def_empty && param->cur_empty ? CPS_DEFAULT : CPS_CHANGED); + param->cached_state |= CPS_EMPTY; + + goto gcpgs_recached; + + } + + switch (param->type) + { + case CPT_BOOLEAN: + param->cached_state = (param->def.boolean && param->cur.boolean ? CPS_DEFAULT : CPS_CHANGED); + break; + + case CPT_INTEGER: + param->cached_state = (param->def.integer == param->cur.integer ? CPS_DEFAULT : CPS_CHANGED); + break; + + case CPT_STRING: + if (param->def.string == NULL && param->cur.string == NULL) + param->cached_state = CPS_DEFAULT; + else if (param->def.string != NULL && param->cur.string != NULL) + param->cached_state = strcmp(param->def.string, param->cur.string) == 0 ? CPS_DEFAULT : CPS_CHANGED; + else + param->cached_state = CPS_CHANGED; + break; + + default: + break; + + } + + gcpgs_recached:; + + } + + return param->cached_state; + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre à mettre à jour. * +* * +* Description : Efface toute valeur courante d'un paramètre de configuration.* +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_config_param_make_empty(GCfgParam *param) +{ + switch (param->type) + { + case CPT_BOOLEAN: + param->cur.boolean = false; + break; + + case CPT_INTEGER: + param->cur.integer = INT_MIN; + break; + + case CPT_STRING: + if (param->cur.string != NULL) + { + free(param->cur.string); + param->cur.string = NULL; + } + break; + + default: + break; + + } + + if (!param->cur_empty) + { + param->cur_empty = true; + + /* Réinitialisation du cache d'état... */ + param->cached_state = CPS_UNDEFINED; + + g_signal_emit_by_name(param, "modified"); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre à mettre à jour. * +* * +* Description : Réinitialise la valeur d'un paramètre de configuration. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_config_param_reset(GCfgParam *param) +{ + bool modified; /* Détermine une modification */ + + modified = !(g_config_param_get_state(param) & CPS_DEFAULT); + + switch (param->type) + { + case CPT_BOOLEAN: + param->cur.boolean = param->def.boolean; + break; + + case CPT_INTEGER: + param->cur.integer = param->def.integer; + break; + + case CPT_STRING: + if (param->def.string != NULL) + param->cur.string = strdup(param->def.string); + else + param->cur.string = NULL; + break; + + default: + assert(false); + break; + + } + + if (modified) + { + param->cur_empty = param->def_empty; + + /* Réinitialisation du cache d'état... */ + param->cached_state = CPS_UNDEFINED; + + g_signal_emit_by_name(param, "modified"); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre à mettre à jour. * +* ... = nouvelle valeur du paramètre. * +* * +* Description : Modifie la valeur courante d'un paramètre de configuration. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_config_param_set_value(GCfgParam *param, ...) +{ + va_list ap; /* Liste d'arguments */ + bool old_boolean; /* Valeur booléenne */ + int old_integer; /* Valeur entière */ + char *old_string; /* Chaîne de caractères */ + bool modified; /* Détermine une modification */ + + va_start(ap, param); + + switch (param->type) + { + case CPT_BOOLEAN: + old_boolean = param->cur.boolean; + param->cur.boolean = va_arg(ap, /*bool*/int); + modified = (old_boolean != param->cur.boolean); + break; + + case CPT_INTEGER: + old_integer = param->cur.integer; + param->cur.integer = va_arg(ap, int); + modified = (old_integer != param->cur.integer); + break; + + case CPT_STRING: + old_string = param->cur.string; + param->cur.string = va_arg(ap, char *); + if (param->cur.string != NULL) + param->cur.string = strdup(param->cur.string); + + if (old_string == NULL && param->cur.string == NULL) + modified = false; + else if (old_string != NULL && param->cur.string != NULL) + modified = (strcmp(old_string, param->cur.string) != 0); + else + modified = true; + + if (old_string != NULL) + free(old_string); + + break; + + default: + assert(false); + modified = false; + break; + + } + + va_end(ap); + + if (modified) + { + param->cur_empty = false; + + /* Réinitialisation du cache d'état... */ + param->cached_state = CPS_UNDEFINED; + + g_signal_emit_by_name(param, "modified"); + + } + +} + + +/****************************************************************************** +* * +* Paramètres : param = paramètre à consulter. * +* ... = zone d'enregistrement de la valeur du paramètre. * +* * +* Description : Indique la valeur courante d'un paramètre de configuration. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_config_param_get_value(GCfgParam *param, ...) +{ + va_list ap; /* Liste d'arguments */ + + va_start(ap, param); + + switch (param->type) + { + case CPT_BOOLEAN: + *(va_arg(ap, bool *)) = param->cur.boolean; + break; + + case CPT_INTEGER: + *(va_arg(ap, int *)) = param->cur.integer; + break; + + case CPT_STRING: + *(va_arg(ap, char **)) = param->cur.string; + break; + + default: + assert(false); + break; + + } + + va_end(ap); + +} + + + +/* ---------------------------------------------------------------------------------- */ +/* GESTION GENERIQUE DE CONFIGURATION */ +/* ---------------------------------------------------------------------------------- */ + + +/* Indique le type défini par la GLib pour les configurations génériques. */ +G_DEFINE_TYPE(GGenConfig, g_generic_config, G_TYPE_OBJECT); + + +/****************************************************************************** +* * +* Paramètres : klass = classe à initialiser. * +* * +* Description : Initialise la classe des blocs de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_generic_config_class_init(GGenConfigClass *klass) +{ + GObjectClass *object; /* Autre version de la classe */ + + object = G_OBJECT_CLASS(klass); + + object->dispose = (GObjectFinalizeFunc/* ! */)g_generic_config_dispose; + object->finalize = (GObjectFinalizeFunc)g_generic_config_finalize; + + +} + + +/****************************************************************************** +* * +* Paramètres : config = instance à initialiser. * +* * +* Description : Initialise une instance de bloc de données binaires. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_generic_config_init(GGenConfig *config) +{ + g_rw_lock_init(&config->params_access); + +} + + +/****************************************************************************** +* * +* Paramètres : config = instance d'objet GLib à traiter. * +* * +* Description : Supprime toutes les références externes. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_generic_config_dispose(GGenConfig *config) +{ + GList *iter; /* Boucle de parcours */ + + for (iter = g_list_first(config->params); + iter != NULL; + iter = g_list_next(iter)) + { + g_object_unref(G_OBJECT(iter->data)); + } + + G_OBJECT_CLASS(g_generic_config_parent_class)->dispose(G_OBJECT(config)); + +} + + +/****************************************************************************** +* * +* Paramètres : config = instance d'objet GLib à traiter. * +* * +* Description : Procède à la libération totale de la mémoire. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +static void g_generic_config_finalize(GGenConfig *config) +{ + free(config->filename); + + g_rw_lock_clear(&config->params_access); + + G_OBJECT_CLASS(g_generic_config_parent_class)->finalize(G_OBJECT(config)); + +} + + +/****************************************************************************** +* * +* Paramètres : name = désignation de la configuration. * +* * +* Description : Crée une description de partie de code vierge. * +* * +* Retour : Elément mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GGenConfig *g_generic_config_new(const char *name) +{ + GGenConfig *result; /* Structure à retourner */ + char *suffix; /* Fin du nom de fichier */ + + result = g_object_new(G_TYPE_GEN_CONFIG, NULL); + + suffix = strdup("chrysalide/"); + suffix = stradd(suffix, name); + suffix = stradd(suffix, ".xml"); + + result->filename = get_xdg_config_dir(suffix); + + free(suffix); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : config = ensemble de paramètres de configuration à consulter.* +* * +* Description : Indique le fichier utilisé pour l'enregistrement XML. * +* * +* Retour : Chemin d'accès, potentiellement non existant. * +* * +* Remarques : - * +* * +******************************************************************************/ + +const char *g_generic_config_get_filename(const GGenConfig *config) +{ + return config->filename; + +} + + +/****************************************************************************** +* * +* Paramètres : config = configuration à mettre à jour. * +* write = précise le type d'accès prévu (lecture/écriture). * +* lock = indique le sens du verrouillage à mener. * +* * +* Description : Met à disposition un encadrement des accès aux paramètres. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_generic_config_lock_unlock(GGenConfig *config, bool write, bool lock) +{ + if (write) + { + if (lock) g_rw_lock_writer_lock(&config->params_access); + else g_rw_lock_writer_unlock(&config->params_access); + } + else + { + if (lock) g_rw_lock_reader_lock(&config->params_access); + else g_rw_lock_reader_unlock(&config->params_access); + } + +} + + +/****************************************************************************** +* * +* Paramètres : config = ensemble de paramètres de configuration à charger. * +* * +* Description : Lit la configuration depuis un fichier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_generic_config_read(GGenConfig *config) +{ + bool result; /* Bilan à retourner */ + int ret; /* Test de présence de fichier */ + xmlDocPtr xdoc; /* Document XML de configurat° */ + xmlXPathContextPtr context; /* Contexte de recherche XPath */ + GList *iter; /* Boucle de parcours */ + + ret = access(config->filename, F_OK); + if (ret != 0) return true; + + if (!open_xml_file(config->filename, &xdoc, &context)) + return false; + + g_generic_config_rlock(config); + + for (result = true, iter = g_list_first(config->params); + result && iter != NULL; + iter = g_list_next(iter)) + { + result = g_config_param_read(G_CFG_PARAM(iter->data), context); + } + + g_generic_config_runlock(config); + + return true; + +} + + +/****************************************************************************** +* * +* Paramètres : config = ensemble de paramètres de configuration à décharger.* +* * +* Description : Ecrit la configuration dans un fichier. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_generic_config_write(GGenConfig *config) +{ + bool result; /* Bilan à retourner */ + int ret; /* Bilan de l'assurance */ + xmlDocPtr xdoc; /* Document XML de configurat° */ + xmlXPathContextPtr context; /* Contexte de recherche XPath */ + GList *iter; /* Boucle de parcours */ + + ret = ensure_path_exists(config->filename); + if (ret != 0) return false; + + if (!create_new_xml_file(&xdoc, &context)) + return false; + + g_generic_config_rlock(config); + + for (result = true, iter = g_list_first(config->params); + result && iter != NULL; + iter = g_list_next(iter)) + { + result = g_config_param_write(G_CFG_PARAM(iter->data), xdoc, context); + } + + g_generic_config_runlock(config); + + save_xml_file(xdoc, config->filename); + + close_xml_file(xdoc, context); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : config = ensemble de paramètres de configuration. * +* path = chemin d'accès au paramètre visé. * +* lock = pose un verrou si ce n'est déjà fait. * +* * +* Description : Retrouve un élément de configuration par son chemin. * +* * +* Retour : Elément trouvé ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCfgParam *_g_generic_config_search(GGenConfig *config, const char *path, bool lock) +{ + GList *item; /* Elément générique de liste */ + GCfgParam fake; /* Faux élément partiel */ + + fake.path = (char *)path; + fake.hash = fnv_64a_hash(path); + + if (lock) + g_generic_config_rlock(config); + + item = g_list_find_custom(config->params, &fake, (GCompareFunc)g_config_param_compare); + + if (lock) + g_generic_config_runlock(config); + + return item ? item->data : NULL; + +} + + +/****************************************************************************** +* * +* Paramètres : config = configuration à mettre à jour. * +* param = paramètre à intégrer dans la configuration. * +* * +* Description : Ajoute un paramètre à une configuration. * +* * +* Retour : Elément mis en place ou NULL en cas d'erreur. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GCfgParam *g_generic_config_add_param(GGenConfig *config, GCfgParam *param) +{ + const char *path; /* Chemin d'accès unique */ + GCfgParam *old; /* Test de présence */ + + path = g_config_param_get_path(param); + + g_generic_config_wlock(config); + + old = _g_generic_config_search(config, path, false); + if (old != NULL) + { + g_object_unref(G_OBJECT(param)); + return NULL; + } + + config->params = g_list_append(config->params, param); + + g_generic_config_wunlock(config); + + return param; + +} + + +/****************************************************************************** +* * +* Paramètres : config = configuration à mettre à jour. * +* path = chemin d'accès au paramètre visé. * +* * +* Description : Retire un paramètre d'une configuration. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void g_generic_config_delete_param(GGenConfig *config, const char *path) +{ + GCfgParam *old; /* Test de présence */ + + g_generic_config_wlock(config); + + old = _g_generic_config_search(config, path, false); + + if (old != NULL) + config->params = g_list_remove(config->params, old); + + g_generic_config_wunlock(config); + +} + + +/****************************************************************************** +* * +* Paramètres : config = configuration à consulter. * +* * +* Description : Renvoie la liste des paramètres de configuration. * +* * +* Retour : Liste d'éléments à parcourir. * +* * +* Remarques : - * +* * +******************************************************************************/ + +GList *g_generic_config_list_params(const GGenConfig *config) +{ + /** + * Un verrou doit être posé ! + * Il n'y a pas d'assert() possible pour le vérifier... + */ + + return config->params; + +} diff --git a/src/glibext/configuration.h b/src/glibext/configuration.h new file mode 100644 index 0000000..84d494f --- /dev/null +++ b/src/glibext/configuration.h @@ -0,0 +1,199 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * configuration.h - prototypes pour les éléments de configuration du programme + * + * Copyright (C) 2009-2012 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA 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. + * + * OpenIDA 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 _GLIBEXT_CONFIGURATION_H +#define _GLIBEXT_CONFIGURATION_H + + +#include <glib-object.h> +#include <stdbool.h> + + + +/* ---------------------------- ELEMENT DE CONFIGURATION ---------------------------- */ + + +/* Types de valeur pour élement de configuration */ +typedef enum _ConfigParamType +{ + CPT_BOOLEAN, /* Valeur booléenne */ + CPT_INTEGER, /* Valeur entière */ + CPT_STRING, /* Chaîne de caractère */ + + CPT_COUNT + +} ConfigParamType; + + +/* Liste dess états d'un paramètre de configuration */ +typedef enum _ConfigParamState +{ + CPS_UNDEFINED = (0 << 0), /* Etat non déterminé */ + CPS_CHANGED = (0 << 1), /* Modification utilisateur */ + CPS_DEFAULT = (1 << 1), /* Valeur par défaut */ + CPS_EMPTY = (1 << 2) /* Valeur vide */ + +} ConfigParamState; + + +#define G_TYPE_CFG_PARAM (g_config_param_get_type()) +#define G_CFG_PARAM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_CFG_PARAM, GCfgParam)) +#define G_IS_CFG_PARAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_CFG_PARAM)) +#define G_CFG_PARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_CFG_PARAM, GCfgParamClass)) +#define G_IS_CFG_PARAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_CFG_PARAM)) +#define G_CFG_PARAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_CFG_PARAM, GCfgParamClass)) + + +/* Configuration générique quelconque (instance) */ +typedef struct _GCfgParam GCfgParam; + +/* Configuration générique quelconque (classe) */ +typedef struct _GCfgParamClass GCfgParamClass; + + +/* Indique le type défini par la GLib pour les configurations géénriques. */ +GType g_config_param_get_type(void); + +/* Crée un paramètre de configuration. */ +GCfgParam *g_config_param_new(const char *, ConfigParamType, ...); + +/* Crée un paramètre de configuration sans valeur. */ +GCfgParam *g_config_param_new_empty(const char *, ConfigParamType); + +/* Etablit une comparaison selon un chemin d'accès. */ +gint g_config_param_compare(const GCfgParam *, const GCfgParam *); + +/* Indique le chemin d'accès utilisé pour un paramètre. */ +const char *g_config_param_get_path(const GCfgParam *); + +/* Indique le type de valeur utilisée par un paramètre. */ +ConfigParamType g_config_param_get_ptype(const GCfgParam *); + +/* Indique le statut d'une valeur utilisée par un paramètre. */ +ConfigParamState g_config_param_get_state(GCfgParam *); + +/* Efface toute valeur courante d'un paramètre de configuration. */ +void g_config_param_make_empty(GCfgParam *); + +/* Réinitialise la valeur d'un paramètre de configuration. */ +void g_config_param_reset(GCfgParam *); + +/* Modifie la valeur courante d'un paramètre de configuration. */ +void g_config_param_set_value(GCfgParam *, ...); + +/* Indique la valeur courante d'un paramètre de configuration. */ +void g_config_param_get_value(GCfgParam *, ...); + + + +/* ----------------------- GESTION GENERIQUE DE CONFIGURATION ----------------------- */ + + +#define G_TYPE_GEN_CONFIG (g_generic_config_get_type()) +#define G_GEN_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GEN_CONFIG, GGenConfig)) +#define G_IS_GEN_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GEN_CONFIG)) +#define G_GEN_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GEN_CONFIG, GGenConfigClass)) +#define G_IS_GEN_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GEN_CONFIG)) +#define G_GEN_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GEN_CONFIG, GGenConfigClass)) + + +/* Configuration générique quelconque (instance) */ +typedef struct _GGenConfig GGenConfig; + +/* Configuration générique quelconque (classe) */ +typedef struct _GGenConfigClass GGenConfigClass; + + +/* Indique le type défini par la GLib pour les configurations génériques. */ +GType g_generic_config_get_type(void); + +/* Crée une description de partie de code vierge. */ +GGenConfig *g_generic_config_new(const char *); + +/* Indique le fichier utilisé pour l'enregistrement XML. */ +const char *g_generic_config_get_filename(const GGenConfig *); + +/* Met à disposition un encadrement des accès aux paramètres. */ +void g_generic_config_lock_unlock(GGenConfig *, bool, bool); + + +#define g_generic_config_wlock(cfg) g_generic_config_lock_unlock(cfg, true, true); +#define g_generic_config_wunlock(cfg) g_generic_config_lock_unlock(cfg, true, false); + +#define g_generic_config_rlock(cfg) g_generic_config_lock_unlock(cfg, false, true); +#define g_generic_config_runlock(cfg) g_generic_config_lock_unlock(cfg, false, false); + + +/* Lit la configuration depuis un fichier. */ +bool g_generic_config_read(GGenConfig *); + +/* Ecrit la configuration dans un fichier. */ +bool g_generic_config_write(GGenConfig *); + +/* Retrouve un élément de configuration par son chemin. */ +GCfgParam *_g_generic_config_search(GGenConfig *, const char *, bool); + + +#define g_generic_config_search(cfg, p) _g_generic_config_search(cfg, p, true) + +#define g_generic_config_set_value(c, p, ...) \ + ({ \ + GCfgParam *__param; \ + __param = g_generic_config_search(c, p); \ + if (__param != NULL) \ + g_config_param_set_value(__param, __VA_ARGS__); \ + __param != NULL ? true : false; \ + }) + +#define g_generic_config_get_value(c, p, ...) \ + ({ \ + GCfgParam *__param; \ + __param = g_generic_config_search(c, p); \ + if (__param != NULL) \ + g_config_param_get_value(__param, __VA_ARGS__); \ + __param != NULL ? true : false; \ + }) + + +/* Ajoute un paramètre à une configuration. */ +GCfgParam *g_generic_config_add_param(GGenConfig *, GCfgParam *); + + +#define g_generic_config_create_param(c, p, t, ...) \ + ({ \ + GCfgParam *__result; \ + __result = g_config_param_new(p, t, __VA_ARGS__); \ + __result = g_generic_config_add_param(c, __result); \ + __result; \ + }) + + +/* Retire un paramètre d'une configuration. */ +void g_generic_config_delete_param(GGenConfig *, const char *); + +/* Renvoie la liste des paramètres de configuration. */ +GList *g_generic_config_list_params(const GGenConfig *); + + + +#endif /* _GLIBEXT_CONFIGURATION_H */ diff --git a/src/glibext/gbuffersegment.c b/src/glibext/gbuffersegment.c index a289cd0..e610a51 100644 --- a/src/glibext/gbuffersegment.c +++ b/src/glibext/gbuffersegment.c @@ -312,7 +312,7 @@ bool g_buffer_segment_compare(const GBufferSegment *segment, const GBufferSegmen { bool result; /* Bilan à retourner */ - result = cmp_fnv_64a(segment->hash, ref->hash); + result = (cmp_fnv_64a(segment->hash, ref->hash) == 0); result &= (strcmp(segment->text, ref->text) == 0); |