summaryrefslogtreecommitdiff
path: root/src/analysis/storage/cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/analysis/storage/cache.c')
-rw-r--r--src/analysis/storage/cache.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/src/analysis/storage/cache.c b/src/analysis/storage/cache.c
new file mode 100644
index 0000000..3d0966b
--- /dev/null
+++ b/src/analysis/storage/cache.c
@@ -0,0 +1,334 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * cache.c - conservation hors mémoire d'objets choisis
+ *
+ * Copyright (C) 2020 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 "cache.h"
+
+
+#include <assert.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <unistd.h>
+
+
+#include "cache-int.h"
+#include "../../core/logs.h"
+
+
+
+/* Initialise la classe des caches d'objets entreposables. */
+static void g_object_cache_class_init(GObjectCacheClass *);
+
+/* Initialise une instance de cache d'objets entreposables. */
+static void g_object_cache_init(GObjectCache *);
+
+/* Supprime toutes les références externes. */
+static void g_object_cache_dispose(GObjectCache *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_object_cache_finalize(GObjectCache *);
+
+
+
+/* Indique le type défini pour un cache d'objets entreposables. */
+G_DEFINE_TYPE(GObjectCache, g_object_cache, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des caches d'objets entreposables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_cache_class_init(GObjectCacheClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_object_cache_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_object_cache_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance à initialiser. *
+* *
+* Description : Initialise une instance de cache d'objets entreposables. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_cache_init(GObjectCache *cache)
+{
+ cache->loaded = NULL;
+
+ cache->filename = NULL;
+ cache->fd = -1;
+
+ cache->containers = NULL;
+ cache->count = 0;
+ cache->free_ptr = 0;
+ g_mutex_init(&cache->mutex);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_cache_dispose(GObjectCache *cache)
+{
+ size_t i; /* Boucle de parcours */
+
+ g_clear_object(&cache->loaded);
+
+ g_mutex_lock(&cache->mutex);
+
+ for (i = 0; i < cache->count; i++)
+ g_clear_object(&cache->containers[i]);
+
+ g_mutex_unlock(&cache->mutex);
+
+ g_mutex_clear(&cache->mutex);
+
+ G_OBJECT_CLASS(g_object_cache_parent_class)->dispose(G_OBJECT(cache));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_cache_finalize(GObjectCache *cache)
+{
+ int ret; /* Bilan d'un appel */
+
+ ret = access(cache->filename, W_OK);
+ if (ret == 0)
+ {
+ ret = unlink(cache->filename);
+ if (ret != 0) LOG_ERROR_N("unlink");
+ }
+
+ free(cache->filename);
+
+ if (cache->containers != NULL)
+ free(cache->containers);
+
+ G_OBJECT_CLASS(g_object_cache_parent_class)->finalize(G_OBJECT(cache));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : loaded = contenu binaire à associer. *
+* *
+* Description : Crée le support d'un cache d'objets entreposables. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GObjectCache *g_object_cache_new(GLoadedContent *loaded)
+{
+ GObjectCache *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_OBJECT_CACHE, NULL);
+
+ if (!g_object_cache_open_for(result, loaded))
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = cache d'objets à manipuler. *
+* loaded = contenu binaire à associer. *
+* *
+* Description : Associe un contenu à un cache d'objets. *
+* *
+* Retour : Bilan de l'opéation. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_object_cache_open_for(GObjectCache *cache, GLoadedContent *loaded)
+{
+ bool result; /* Bilan à retourner */
+ GBinContent *content; /* Contenu binaire traité */
+ const gchar *checksum; /* Empreinte de ce contenu */
+
+ result = (cache->loaded == NULL);
+ assert(result);
+
+ if (result) goto done;
+
+ cache->loaded = loaded;
+ g_object_ref(G_OBJECT(loaded));
+
+ /* Constitution du fichier de cache */
+
+ content = g_loaded_content_get_content(loaded);
+
+ checksum = g_binary_content_get_checksum(content);
+
+ asprintf(&cache->filename, "/dev/shm/%s.cache", checksum);
+
+ g_object_unref(G_OBJECT(content));
+
+ /* Ouverture dudit fichier */
+
+ cache->fd = open(cache->filename, O_CREAT | O_TRUNC | O_LARGEFILE, 0600);
+ if (cache->fd == -1)
+ {
+ LOG_ERROR_N("open");
+ result = false;
+ goto done;
+ }
+
+ /* Préparation du cache */
+
+ cache->count = 1000;
+
+ cache->containers = calloc(cache->count, sizeof(GCacheContainer *));
+
+ result = true;
+
+ done:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : cache = cache d'objets à manipuler. *
+* container = objet à placer dans le cache. *
+* *
+* Description : Introduit un contenu dans un cache d'objets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_object_cache_add(GObjectCache *cache, GCacheContainer *container)
+{
+ bool loop; /* Détection de trop-plein */
+ size_t i; /* Boucle de parcours */
+
+ /* Recherche d'un emplacement libre */
+
+ loop = false;
+
+ i = cache->free_ptr;
+
+ do
+ {
+ if (cache->containers[i] != NULL)
+ {
+ g_cache_container_lock_unlock(cache->containers[i], true);
+
+ if (g_cache_container_can_store(cache->containers[i]))
+ {
+ if (true) // TODO
+ g_clear_object(&cache->containers[i]);
+ }
+
+ g_cache_container_lock_unlock(cache->containers[i], false);
+
+ }
+
+ if (cache->containers[i] == NULL)
+ break;
+
+ i++;
+
+ if (i == cache->count)
+ i = 0;
+
+ loop = (i == cache->free_ptr);
+
+ } while (!loop);
+
+ if (loop)
+ {
+ log_simple_message(LMT_WARNING, _("Instruction cache is full!"));
+ goto exit;
+ }
+
+ /* Inscription à la liste des sursis */
+
+ cache->containers[i] = container;
+
+ cache->free_ptr = (i + 1);
+
+ if (cache->free_ptr == cache->count)
+ cache->free_ptr = 0;
+
+ exit:
+
+ ;
+
+}