635 lines
12 KiB
C
635 lines
12 KiB
C
/******************************************************************************
|
|
* @file tool_registry.c
|
|
* @brief Implémentation du registre des outils externes.
|
|
******************************************************************************/
|
|
|
|
#include "core/tool_registry.h"
|
|
|
|
/**
|
|
* @struct ToolInfo
|
|
* @brief Informations internes décrivant un outil externe.
|
|
*/
|
|
struct ToolInfo
|
|
{
|
|
char *identifier;
|
|
char *display_name;
|
|
char *executable_name;
|
|
|
|
ToolRequirement requirement;
|
|
ToolAvailability availability;
|
|
|
|
char *resolved_path;
|
|
char *detected_version;
|
|
};
|
|
|
|
/**
|
|
* @struct ToolRegistry
|
|
* @brief Registre interne des outils externes.
|
|
*/
|
|
struct ToolRegistry
|
|
{
|
|
GPtrArray *tools;
|
|
};
|
|
|
|
/**
|
|
* @brief Vérifie qu'une chaîne est définie et non vide.
|
|
*
|
|
* @param text Chaîne à vérifier.
|
|
*
|
|
* @return TRUE si la chaîne est valide.
|
|
*/
|
|
static gboolean tool_registry_string_is_valid(
|
|
const char *text
|
|
)
|
|
{
|
|
return text != NULL &&
|
|
text[0] != '\0';
|
|
}
|
|
|
|
/**
|
|
* @brief Vérifie qu'une importance de dépendance est valide.
|
|
*
|
|
* @param requirement Valeur à vérifier.
|
|
*
|
|
* @return TRUE si la valeur est reconnue.
|
|
*/
|
|
static gboolean tool_registry_requirement_is_valid(
|
|
ToolRequirement requirement
|
|
)
|
|
{
|
|
return requirement == TOOL_REQUIREMENT_OPTIONAL ||
|
|
requirement == TOOL_REQUIREMENT_REQUIRED;
|
|
}
|
|
|
|
/**
|
|
* @brief Libère un outil et toutes ses chaînes.
|
|
*
|
|
* Cette fonction est utilisée comme fonction de destruction du GPtrArray.
|
|
*
|
|
* @param user_data Pointeur vers ToolInfo.
|
|
*/
|
|
static void tool_info_free(
|
|
gpointer user_data
|
|
)
|
|
{
|
|
ToolInfo *tool_info = user_data;
|
|
|
|
if (tool_info == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
g_clear_pointer(
|
|
&tool_info->identifier,
|
|
g_free
|
|
);
|
|
|
|
g_clear_pointer(
|
|
&tool_info->display_name,
|
|
g_free
|
|
);
|
|
|
|
g_clear_pointer(
|
|
&tool_info->executable_name,
|
|
g_free
|
|
);
|
|
|
|
g_clear_pointer(
|
|
&tool_info->resolved_path,
|
|
g_free
|
|
);
|
|
|
|
g_clear_pointer(
|
|
&tool_info->detected_version,
|
|
g_free
|
|
);
|
|
|
|
g_free(
|
|
tool_info
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @brief Recherche un outil modifiable dans le registre.
|
|
*
|
|
* @param tool_registry Registre consulté.
|
|
* @param identifier Identifiant recherché.
|
|
*
|
|
* @return Outil correspondant, ou NULL.
|
|
*/
|
|
static ToolInfo *tool_registry_find_internal(
|
|
const ToolRegistry *tool_registry,
|
|
const char *identifier
|
|
)
|
|
{
|
|
guint index = 0;
|
|
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL ||
|
|
!tool_registry_string_is_valid(identifier))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for (index = 0;
|
|
index < tool_registry->tools->len;
|
|
index++)
|
|
{
|
|
ToolInfo *tool_info = NULL;
|
|
|
|
tool_info = g_ptr_array_index(
|
|
tool_registry->tools,
|
|
index
|
|
);
|
|
|
|
if (tool_info != NULL &&
|
|
g_strcmp0(
|
|
tool_info->identifier,
|
|
identifier
|
|
) == 0)
|
|
{
|
|
return tool_info;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
GQuark tool_registry_error_quark(void)
|
|
{
|
|
return g_quark_from_static_string(
|
|
"labfy-investigation-tool-registry-error"
|
|
);
|
|
}
|
|
|
|
ToolRegistry *tool_registry_new(void)
|
|
{
|
|
ToolRegistry *tool_registry = NULL;
|
|
|
|
tool_registry = g_new0(
|
|
ToolRegistry,
|
|
1
|
|
);
|
|
|
|
tool_registry->tools =
|
|
g_ptr_array_new_with_free_func(
|
|
tool_info_free
|
|
);
|
|
|
|
return tool_registry;
|
|
}
|
|
|
|
void tool_registry_free(
|
|
ToolRegistry *tool_registry
|
|
)
|
|
{
|
|
if (tool_registry == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (tool_registry->tools != NULL)
|
|
{
|
|
g_ptr_array_unref(
|
|
tool_registry->tools
|
|
);
|
|
|
|
tool_registry->tools = NULL;
|
|
}
|
|
|
|
g_free(
|
|
tool_registry
|
|
);
|
|
}
|
|
|
|
gboolean tool_registry_register(
|
|
ToolRegistry *tool_registry,
|
|
const char *identifier,
|
|
const char *display_name,
|
|
const char *executable_name,
|
|
ToolRequirement requirement,
|
|
GError **error
|
|
)
|
|
{
|
|
ToolInfo *tool_info = NULL;
|
|
|
|
g_return_val_if_fail(
|
|
error == NULL || *error == NULL,
|
|
FALSE
|
|
);
|
|
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL ||
|
|
!tool_registry_string_is_valid(identifier) ||
|
|
!tool_registry_string_is_valid(display_name) ||
|
|
!tool_registry_string_is_valid(executable_name) ||
|
|
!tool_registry_requirement_is_valid(requirement))
|
|
{
|
|
g_set_error_literal(
|
|
error,
|
|
TOOL_REGISTRY_ERROR,
|
|
TOOL_REGISTRY_ERROR_INVALID_ARGUMENT,
|
|
"Les arguments fournis au registre d'outils sont invalides."
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (tool_registry_find_internal(
|
|
tool_registry,
|
|
identifier
|
|
) != NULL)
|
|
{
|
|
g_set_error(
|
|
error,
|
|
TOOL_REGISTRY_ERROR,
|
|
TOOL_REGISTRY_ERROR_DUPLICATE_IDENTIFIER,
|
|
"Un outil portant l'identifiant '%s' est déjà enregistré.",
|
|
identifier
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
tool_info = g_new0(
|
|
ToolInfo,
|
|
1
|
|
);
|
|
|
|
tool_info->identifier = g_strdup(
|
|
identifier
|
|
);
|
|
|
|
tool_info->display_name = g_strdup(
|
|
display_name
|
|
);
|
|
|
|
tool_info->executable_name = g_strdup(
|
|
executable_name
|
|
);
|
|
|
|
tool_info->requirement = requirement;
|
|
tool_info->availability =
|
|
TOOL_AVAILABILITY_UNKNOWN;
|
|
|
|
tool_info->resolved_path = NULL;
|
|
tool_info->detected_version = NULL;
|
|
|
|
g_ptr_array_add(
|
|
tool_registry->tools,
|
|
tool_info
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean tool_registry_refresh(
|
|
ToolRegistry *tool_registry,
|
|
GError **error
|
|
)
|
|
{
|
|
guint index = 0;
|
|
|
|
g_return_val_if_fail(
|
|
error == NULL || *error == NULL,
|
|
FALSE
|
|
);
|
|
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL)
|
|
{
|
|
g_set_error_literal(
|
|
error,
|
|
TOOL_REGISTRY_ERROR,
|
|
TOOL_REGISTRY_ERROR_INVALID_ARGUMENT,
|
|
"Le registre d'outils est invalide."
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
for (index = 0;
|
|
index < tool_registry->tools->len;
|
|
index++)
|
|
{
|
|
ToolInfo *tool_info = NULL;
|
|
char *found_path = NULL;
|
|
char *canonical_path = NULL;
|
|
|
|
tool_info = g_ptr_array_index(
|
|
tool_registry->tools,
|
|
index
|
|
);
|
|
|
|
if (tool_info == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
found_path = g_find_program_in_path(
|
|
tool_info->executable_name
|
|
);
|
|
|
|
g_clear_pointer(
|
|
&tool_info->resolved_path,
|
|
g_free
|
|
);
|
|
|
|
if (found_path == NULL)
|
|
{
|
|
tool_info->availability =
|
|
TOOL_AVAILABILITY_MISSING;
|
|
|
|
continue;
|
|
}
|
|
|
|
/*
|
|
* g_find_program_in_path() retourne une nouvelle chaîne.
|
|
*
|
|
* La canonicalisation garantit que le registre mémorise un
|
|
* chemin absolu et normalisé.
|
|
*/
|
|
canonical_path = g_canonicalize_filename(
|
|
found_path,
|
|
NULL
|
|
);
|
|
|
|
g_free(
|
|
found_path
|
|
);
|
|
|
|
tool_info->resolved_path =
|
|
canonical_path;
|
|
|
|
tool_info->availability =
|
|
TOOL_AVAILABILITY_AVAILABLE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gsize tool_registry_get_count(
|
|
const ToolRegistry *tool_registry
|
|
)
|
|
{
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return tool_registry->tools->len;
|
|
}
|
|
|
|
const ToolInfo *tool_registry_get_tool(
|
|
const ToolRegistry *tool_registry,
|
|
gsize index
|
|
)
|
|
{
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL ||
|
|
index >= tool_registry->tools->len)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return g_ptr_array_index(
|
|
tool_registry->tools,
|
|
(guint) index
|
|
);
|
|
}
|
|
|
|
const ToolInfo *tool_registry_find(
|
|
const ToolRegistry *tool_registry,
|
|
const char *identifier
|
|
)
|
|
{
|
|
return tool_registry_find_internal(
|
|
tool_registry,
|
|
identifier
|
|
);
|
|
}
|
|
|
|
gboolean tool_registry_set_version(
|
|
ToolRegistry *tool_registry,
|
|
const char *identifier,
|
|
const char *detected_version,
|
|
GError **error
|
|
)
|
|
{
|
|
ToolInfo *tool_info = NULL;
|
|
|
|
g_return_val_if_fail(
|
|
error == NULL || *error == NULL,
|
|
FALSE
|
|
);
|
|
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL ||
|
|
!tool_registry_string_is_valid(identifier))
|
|
{
|
|
g_set_error_literal(
|
|
error,
|
|
TOOL_REGISTRY_ERROR,
|
|
TOOL_REGISTRY_ERROR_INVALID_ARGUMENT,
|
|
"Le registre ou l'identifiant de l'outil est invalide."
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
tool_info = tool_registry_find_internal(
|
|
tool_registry,
|
|
identifier
|
|
);
|
|
|
|
if (tool_info == NULL)
|
|
{
|
|
g_set_error(
|
|
error,
|
|
TOOL_REGISTRY_ERROR,
|
|
TOOL_REGISTRY_ERROR_NOT_FOUND,
|
|
"Aucun outil portant l'identifiant '%s' n'est enregistré.",
|
|
identifier
|
|
);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
g_clear_pointer(
|
|
&tool_info->detected_version,
|
|
g_free
|
|
);
|
|
|
|
if (tool_registry_string_is_valid(
|
|
detected_version
|
|
))
|
|
{
|
|
tool_info->detected_version =
|
|
g_strdup(
|
|
detected_version
|
|
);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean tool_registry_has_missing_required_tools(
|
|
const ToolRegistry *tool_registry
|
|
)
|
|
{
|
|
guint index = 0;
|
|
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for (index = 0;
|
|
index < tool_registry->tools->len;
|
|
index++)
|
|
{
|
|
const ToolInfo *tool_info = NULL;
|
|
|
|
tool_info = g_ptr_array_index(
|
|
tool_registry->tools,
|
|
index
|
|
);
|
|
|
|
if (tool_info != NULL &&
|
|
tool_info->requirement ==
|
|
TOOL_REQUIREMENT_REQUIRED &&
|
|
tool_info->availability ==
|
|
TOOL_AVAILABILITY_MISSING)
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
gboolean tool_registry_all_required_tools_available(
|
|
const ToolRegistry *tool_registry
|
|
)
|
|
{
|
|
guint index = 0;
|
|
|
|
if (tool_registry == NULL ||
|
|
tool_registry->tools == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for (index = 0;
|
|
index < tool_registry->tools->len;
|
|
index++)
|
|
{
|
|
const ToolInfo *tool_info = NULL;
|
|
|
|
tool_info = g_ptr_array_index(
|
|
tool_registry->tools,
|
|
index
|
|
);
|
|
|
|
if (tool_info != NULL &&
|
|
tool_info->requirement ==
|
|
TOOL_REQUIREMENT_REQUIRED &&
|
|
tool_info->availability !=
|
|
TOOL_AVAILABILITY_AVAILABLE)
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Lorsqu'aucun outil obligatoire n'est enregistré, toutes les
|
|
* dépendances obligatoires sont considérées comme satisfaites.
|
|
*/
|
|
return TRUE;
|
|
}
|
|
|
|
const char *tool_info_get_identifier(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return tool_info->identifier;
|
|
}
|
|
|
|
const char *tool_info_get_display_name(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return tool_info->display_name;
|
|
}
|
|
|
|
const char *tool_info_get_executable_name(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return tool_info->executable_name;
|
|
}
|
|
|
|
ToolRequirement tool_info_get_requirement(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return TOOL_REQUIREMENT_OPTIONAL;
|
|
}
|
|
|
|
return tool_info->requirement;
|
|
}
|
|
|
|
ToolAvailability tool_info_get_availability(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return TOOL_AVAILABILITY_UNKNOWN;
|
|
}
|
|
|
|
return tool_info->availability;
|
|
}
|
|
|
|
const char *tool_info_get_resolved_path(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return tool_info->resolved_path;
|
|
}
|
|
|
|
const char *tool_info_get_detected_version(
|
|
const ToolInfo *tool_info
|
|
)
|
|
{
|
|
if (tool_info == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return tool_info->detected_version;
|
|
}
|