diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2025-03-13 00:19:58 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2025-03-13 00:19:58 (GMT) |
commit | 733d0cdb8677fe09310125bcaeb058a1a9c56b4d (patch) | |
tree | 17b8d9a151068dac695d25e39e875933ff9aaa40 /src | |
parent | 8287d20061887e9fd33e038e8f9bf86cf13f2780 (diff) |
Rebuild a generic storage for GObjects using a ZIP format.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/common/cpp.h | 7 | ||||
-rw-r--r-- | src/glibext/Makefile.am | 8 | ||||
-rw-r--r-- | src/glibext/serialize-int.h | 18 | ||||
-rw-r--r-- | src/glibext/serialize.c | 28 | ||||
-rw-r--r-- | src/glibext/serialize.h | 38 | ||||
-rw-r--r-- | src/glibext/storage-int.h | 21 | ||||
-rw-r--r-- | src/glibext/storage.c | 994 | ||||
-rw-r--r-- | src/glibext/storage.h | 70 | ||||
-rw-r--r-- | src/glibext/tpmem-int.h | 78 | ||||
-rw-r--r-- | src/glibext/tpmem.c | 224 | ||||
-rw-r--r-- | src/glibext/tpmem.h | 41 |
12 files changed, 904 insertions, 625 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index c50af8f..cfd1a4d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -86,7 +86,7 @@ libchrysacore4_la_LIBADD = \ plugins/libplugins.la libchrysacore4_la_LDFLAGS = \ - $(TOOLKIT_LIBS) $(LIBSSL_LIBS) $(LIBJSONGLIB_LIBS) + $(TOOLKIT_LIBS) $(LIBSSL_LIBS) $(LIBJSONGLIB_LIBS) $(LIBZIP_LIBS) if BUILD_CURL_SUPPORT diff --git a/src/common/cpp.h b/src/common/cpp.h index 2644281..9616db3 100644 --- a/src/common/cpp.h +++ b/src/common/cpp.h @@ -43,6 +43,13 @@ /** + * Facilite la transmission d'arguement pour des fonctions + * comme strncmp() et Cie. + */ +#define SL(str) str, strlen(str) + + +/** * Détermine la taille de la plus longue chaîne de caractères * correspondant à un type donné. */ diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 81d13d2..f946665 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -49,10 +49,16 @@ libglibext_la_SOURCES = \ portion.h portion.c \ secstorage-int.h \ secstorage.h secstorage.c \ + serialize-int.h \ + serialize.h serialize.c \ singleton-int.h \ singleton.h singleton.c \ + storage-int.h \ + storage.h storage.c \ strbuilder-int.h \ strbuilder.h strbuilder.c \ + tpmem-int.h \ + tpmem.h tpmem.c \ work-int.h \ work.h work.c \ workgroup-int.h \ @@ -60,7 +66,7 @@ libglibext_la_SOURCES = \ workqueue-int.h \ workqueue.h workqueue.c -libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) +libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBZIP_CFLAGS) RES_FILES = \ diff --git a/src/glibext/serialize-int.h b/src/glibext/serialize-int.h index de8d3e3..df9c597 100644 --- a/src/glibext/serialize-int.h +++ b/src/glibext/serialize-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * serialize-int.h - définitions internes propres aux objets entreposables dans un cache * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,8 +21,8 @@ */ -#ifndef _ANALYSIS_STORAGE_SERIALIZE_INT_H -#define _ANALYSIS_STORAGE_SERIALIZE_INT_H +#ifndef _GLIBEXT_SERIALIZE_INT_H +#define _GLIBEXT_SERIALIZE_INT_H #include "serialize.h" @@ -33,14 +33,14 @@ /* Charge un objet depuis une mémoire tampon. */ -typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, packed_buffer_t *); +typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, int); /* Sauvegarde un objet dans une mémoire tampon. */ -typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, packed_buffer_t *); +typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, int); /* Intermédiaire pour la mise en cache d'objet (interface) */ -struct _GSerializableObjectIface +struct _GSerializableObjectInterface { GTypeInterface base_iface; /* A laisser en premier */ @@ -50,9 +50,5 @@ struct _GSerializableObjectIface }; -/* Redéfinition */ -typedef GSerializableObjectIface GSerializableObjectInterface; - - -#endif /* _ANALYSIS_STORAGE_SERIALIZE_INT_H */ +#endif /* _GLIBEXT_SERIALIZE_INT_H */ diff --git a/src/glibext/serialize.c b/src/glibext/serialize.c index d1b0502..b43f0c2 100644 --- a/src/glibext/serialize.c +++ b/src/glibext/serialize.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * serialize.h - objets entreposables dans un cache * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -51,6 +51,8 @@ G_DEFINE_INTERFACE(GSerializableObject, g_serializable_object, G_TYPE_OBJECT) static void g_serializable_object_default_init(GSerializableObjectInterface *iface) { + iface->load = NULL; + iface->store = NULL; } @@ -58,10 +60,10 @@ static void g_serializable_object_default_init(GSerializableObjectInterface *ifa /****************************************************************************** * * * Paramètres : object = élément GLib à constuire. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à lire. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en lecture. * * * -* Description : Charge un objet depuis une mémoire tampon. * +* Description : Charge un objet depuis un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -69,14 +71,14 @@ static void g_serializable_object_default_init(GSerializableObjectInterface *ifa * * ******************************************************************************/ -bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) +bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GSerializableObjectIface *iface; /* Interface utilisée */ + GSerializableObjectInterface *iface; /* Interface utilisée */ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - result = iface->load(object, storage, pbuf); + result = iface->load(object, storage, fd); return result; @@ -86,10 +88,10 @@ bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *sto /****************************************************************************** * * * Paramètres : object = élément GLib à consulter. * -* storage = conservateur de données à manipuler ou NULL. * -* pbuf = zone tampon à remplir. * +* storage = conservateur de données à manipuler. * +* fd = flux ouvert en écriture. * * * -* Description : Sauvegarde un objet dans une mémoire tampon. * +* Description : Sauvegarde un objet dans un flux de données. * * * * Retour : Bilan de l'opération. * * * @@ -97,14 +99,14 @@ bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *sto * * ******************************************************************************/ -bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, packed_buffer_t *pbuf) +bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, int fd) { bool result; /* Bilan à retourner */ - GSerializableObjectIface *iface; /* Interface utilisée */ + GSerializableObjectInterface *iface; /* Interface utilisée */ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object); - result = iface->store(object, storage, pbuf); + result = iface->store(object, storage, fd); return result; diff --git a/src/glibext/serialize.h b/src/glibext/serialize.h index 93a4496..c95ac30 100644 --- a/src/glibext/serialize.h +++ b/src/glibext/serialize.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * serialize.h - prototypes pour les objets entreposables dans un cache * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,44 +21,32 @@ */ -#ifndef _ANALYSIS_STORAGE_SERIALIZE_H -#define _ANALYSIS_STORAGE_SERIALIZE_H +#ifndef _GLIBEXT_SERIALIZE_H +#define _GLIBEXT_SERIALIZE_H -#include <glib-object.h> +#include <stdbool.h> -#include "../../common/packed.h" +#include "helpers.h" -#define G_TYPE_SERIALIZABLE_OBJECT g_serializable_object_get_type() -#define G_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObject)) -#define G_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface)) -#define G_IS_SERIALIZABLE_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_SERIALIZABLE_OBJECT)) -#define G_IS_SERIALIZABLE_OBJECT_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), G_TYPE_SERIALIZABLE_OBJECT)) -#define G_SERIALIZABLE_OBJECT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), G_TYPE_SERIALIZABLE_OBJECT, GSerializableObjectIface)) +#define G_TYPE_SERIALIZABLE_OBJECT (g_serializable_object_get_type()) +DECLARE_INTERFACE(GSerializableObject, g_serializable_object, G, SERIALIZABLE_OBJECT); -/* Intermédiaire pour la mise en cache d'objet (coquille vide) */ -typedef struct _GSerializableObject GSerializableObject; - -/* Intermédiaire pour la mise en cache d'objet (interface) */ -typedef struct _GSerializableObjectIface GSerializableObjectIface; - - -/* Détermine le type d'une interface pour la mise en cache d'objet. */ -GType g_serializable_object_get_type(void) G_GNUC_CONST; /* storage.h : définition d'une conservation d'objets construits */ typedef struct _GObjectStorage GObjectStorage; -/* Charge un objet depuis une mémoire tampon. */ -bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, packed_buffer_t *); -/* Sauvegarde un objet dans une mémoire tampon. */ -bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, packed_buffer_t *); +/* Charge un objet depuis un flux de données. */ +bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, int); + +/* Sauvegarde un objet dans un flux de données. */ +bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, int); -#endif /* _ANALYSIS_STORAGE_SERIALIZE_H */ +#endif /* _GLIBEXT_SERIALIZE_H */ diff --git a/src/glibext/storage-int.h b/src/glibext/storage-int.h index 4883aa8..e4bac7a 100644 --- a/src/glibext/storage-int.h +++ b/src/glibext/storage-int.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * storage.h - prototypes internes pour la conservation sur disque d'objets construits * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,11 +21,13 @@ */ -#ifndef _ANALYSIS_STORAGE_STORAGE_INT_H -#define _ANALYSIS_STORAGE_STORAGE_INT_H +#ifndef _GLIBEXT_STORAGE_INT_H +#define _GLIBEXT_STORAGE_INT_H #include "storage.h" +#include "tpmem.h" +#include "../common/szbin.h" @@ -44,9 +46,12 @@ struct _GObjectStorage { GObject parent; /* A laisser en premier */ - GTypeMemory *tpmem; /* Mémorisation de types */ + sized_binary_t type; /* Type de conservation */ + uint8_t version; /* Version correspondante */ + + sized_binary_t uid; /* Identifiant de distinction */ - char *hash; /* Empreinte du contenu */ + GTypeMemory *tpmem; /* Mémorisation de types */ storage_backend_t *backends; /* Gestionnaires existants */ size_t count; /* Quantité de gestionnaires */ @@ -62,5 +67,9 @@ struct _GObjectStorageClass }; +/* Met en place un support d'une conservation d'objets en place. */ +bool g_object_storage_create(GObjectStorage *, const char *, uint8_t, const char *); + + -#endif /* _ANALYSIS_STORAGE_STORAGE_INT_H */ +#endif /* _GLIBEXT_STORAGE_INT_H */ diff --git a/src/glibext/storage.c b/src/glibext/storage.c index 610a0f6..0e6620b 100644 --- a/src/glibext/storage.c +++ b/src/glibext/storage.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * storage.c - conservation hors mémoire d'objets choisis * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -28,20 +28,23 @@ #include <malloc.h> #include <string.h> #include <unistd.h> -#include <stdarg.h> +#include <zip.h> #include "storage-int.h" -#include "../db/misc/rlestr.h" -#include "../../common/io.h" -#include "../../common/leb128.h" -#include "../../common/pathname.h" -#include "../../core/logs.h" +#include "../common/cpp.h" +#include "../common/pathname.h" +#include "../core/logs.h" - -#define STORAGE_MAGIC "CSTR" -#define STORAGE_NUMBER "\x00\x01" +/** + * Historique du format : + * + * - 09/03/25 : 1.0 (version initiale) + * + */ +#define STORAGE_MAGIC "COBSTR" +#define STORAGE_NUMBER "\x01\x00" /* Initialise la classe des conservations d'objets en place. */ @@ -51,10 +54,13 @@ static void g_object_storage_class_init(GObjectStorageClass *); static void g_object_storage_init(GObjectStorage *); /* Supprime toutes les références externes. */ -static void g_object_storage_dispose(GObjectStorage *); +static void g_object_storage_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_object_storage_finalize(GObjectStorage *); +static void g_object_storage_finalize(GObject *); + +/* Assure l'inexistence d'un groupe avec un nom donné. */ +static bool g_object_storage_has_no_backend_named(GObjectStorage *, const char *); /* Retrouve l'encadrement pour un nouveau groupe d'objets. */ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const char *); @@ -62,11 +68,8 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const /* Ajoute le support d'un nouveau groupe d'objets construits. */ static bool g_object_storage_add_backend(GObjectStorage *, const char *, storage_backend_t **); -/* Extrait d'un tampon des enregistrements spécifiques. */ -static bool g_object_storage_load_backend(GObjectStorage *, packed_buffer_t *); - -/* Place dans un tampon les données liées à des enregistrements. */ -static bool pack_storage_backend(const storage_backend_t *, packed_buffer_t *); +/* Charge un objet à partir de données rassemblées. */ +static GSerializableObject *g_object_storage_load_object_unlocked(GObjectStorage *, const char *, off64_t); @@ -92,8 +95,8 @@ static void g_object_storage_class_init(GObjectStorageClass *klass) object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_object_storage_dispose; - object->finalize = (GObjectFinalizeFunc)g_object_storage_finalize; + object->dispose = g_object_storage_dispose; + object->finalize = g_object_storage_finalize; } @@ -112,9 +115,12 @@ static void g_object_storage_class_init(GObjectStorageClass *klass) static void g_object_storage_init(GObjectStorage *storage) { - storage->tpmem = g_type_memory_new(); + init_sized_binary(&storage->type); + storage->version = 0; - storage->hash = NULL; + init_sized_binary(&storage->uid); + + storage->tpmem = g_type_memory_new(); storage->backends = NULL; storage->count = 0; @@ -125,7 +131,7 @@ static void g_object_storage_init(GObjectStorage *storage) /****************************************************************************** * * -* Paramètres : storage = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -135,18 +141,22 @@ static void g_object_storage_init(GObjectStorage *storage) * * ******************************************************************************/ -static void g_object_storage_dispose(GObjectStorage *storage) +static void g_object_storage_dispose(GObject *object) { + GObjectStorage *storage; /* Version spécialisée */ + + storage = G_OBJECT_STORAGE(object); + g_clear_object(&storage->tpmem); - G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(G_OBJECT(storage)); + G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : storage = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -156,18 +166,27 @@ static void g_object_storage_dispose(GObjectStorage *storage) * * ******************************************************************************/ -static void g_object_storage_finalize(GObjectStorage *storage) +static void g_object_storage_finalize(GObject *object) { + GObjectStorage *storage; /* Version spécialisée */ size_t i; /* Boucle de parcours */ storage_backend_t *backend; /* Gestionnaire à manipuler */ int ret; /* Bilan d'un appel */ + storage = G_OBJECT_STORAGE(object); + g_mutex_lock(&storage->mutex); for (i = 0; i < storage->count; i++) { backend = &storage->backends[i]; + /** + * Chargement incomplet depuis g_object_storage_load(). + */ + if (backend->name == NULL) + break; + if (backend->fd != -1) close(backend->fd); else @@ -193,17 +212,20 @@ static void g_object_storage_finalize(GObjectStorage *storage) g_mutex_clear(&storage->mutex); - if (storage->hash != NULL) - free(storage->hash); + exit_sized_binary(&storage->type); + + exit_sized_binary(&storage->uid); - G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(G_OBJECT(storage)); + G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(object); } /****************************************************************************** * * -* Paramètres : loaded = contenu binaire à associer. * +* Paramètres : type = type global à indiquer dans une conservation. * +* version = numéro de version associé. * +* uid = identifiant arbitraire mais unique pour distinguer.* * * * Description : Crée le support d'une conservation d'objets en place. * * * @@ -213,13 +235,14 @@ static void g_object_storage_finalize(GObjectStorage *storage) * * ******************************************************************************/ -GObjectStorage *g_object_storage_new(const char *hash) +GObjectStorage *g_object_storage_new(const char *type, uint8_t version, const char *uid) { GObjectStorage *result; /* Structure à retourner */ result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); - result->hash = strdup(hash); + if (!g_object_storage_create(result, type, version, uid)) + g_clear_object(&result); return result; @@ -228,7 +251,39 @@ GObjectStorage *g_object_storage_new(const char *hash) /****************************************************************************** * * -* Paramètres : pbuf = zone tampon à lire. * +* Paramètres : storage = stockage d'objets à initialiser. * +* type = type global à indiquer dans une conservation. * +* version = numéro de version associé. * +* uid = identifiant arbitraire mais unique pour distinguer.* +* * +* Description : Met en place un support d'une conservation d'objets en place.* +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool g_object_storage_create(GObjectStorage *storage, const char *type, uint8_t version, const char *uid) +{ + bool result; /* Bilan à retourner */ + + result = true; + + dup_into_sized_binary(&storage->type, type, strlen(type)); + + storage->version = version; + + dup_into_sized_binary(&storage->uid, uid, strlen(uid) + 1); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : filename = fichier de source à traiter. * * * * Description : Charge le support d'une conservation d'objets en place. * * * @@ -238,140 +293,297 @@ GObjectStorage *g_object_storage_new(const char *hash) * * ******************************************************************************/ -GObjectStorage *g_object_storage_load(packed_buffer_t *pbuf) +GObjectStorage *g_object_storage_load(const char *filename) { GObjectStorage *result; /* Structure à retourner */ - char header[6]; /* Entête attendue des données */ + GObjectStorage *storage; /* Structure en construction */ + int err; /* Eventuel code d'erreur */ + zip_t *archive; /* Archive ZIP à manipuler */ + zip_error_t error; /* Suivi des erreurs obtenues */ + char *tpmem_filename; /* Chemin d'accès pour types */ + zip_int64_t entries_count; /* Nombre d'éléments ZIP */ + void *data; /* Données (décompressées) */ + zip_stat_t stats; /* Information sur les données */ + zip_file_t *file; /* Echantillon à extraire */ + zip_int64_t got; /* Nombre d'octets lus */ + int ret; /* Bilan d'un appel */ + const void *pos; /* Tête de lecture */ + const void *max; /* Fin des données lisibles */ bool status; /* Bilan d'une extraction */ - rle_string str; /* Chaîne à conserver */ - uleb128_t count; /* Nombre de groupes à charger */ - uleb128_t i; /* Boucle de parcours */ + char *prefix; /* Début de nom de fichier */ + int fd; /* Descripteur de flux ouvert */ + off_t moved; /* Nouvelle position établie */ + zip_int64_t i; /* Boucle de parcours */ + storage_backend_t *backend; /* Informations à intégrer */ + const char *slash; /* Pointeur vers un caractère /*/ result = NULL; - status = extract_packed_buffer(pbuf, header, 6, false); - if (!status) goto quick_exit; + storage = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); - if (strncmp(header, STORAGE_MAGIC STORAGE_NUMBER, 6) != 0) - goto quick_exit; + archive = zip_open(filename, ZIP_RDONLY, &err); + if (archive == NULL) + { + zip_error_init_with_code(&error, err); + LOG_ERROR_ZIP("zip_open", &error); + goto exit; + } + + zip_error_init(&error); + + tpmem_filename = NULL; + + /* Validation du nombre d'entrées */ + + entries_count = zip_get_num_entries(archive, ZIP_FL_UNCHANGED); - setup_empty_rle_string(&str); + if (entries_count < 2) + goto exit_with_archive; - status = unpack_rle_string(&str, pbuf); - if (!status) goto quick_exit; + data = NULL; - if (get_rle_string(&str) == NULL) + /* Extraction de la partie de contrôle */ + + ret = zip_stat_index(archive, 0, ZIP_FL_UNCHANGED, &stats); + if (ret != 0) { - exit_rle_string(&str); - goto quick_exit; + LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive)); + goto exit_with_archive; } - result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL); - - result->hash = strdup(get_rle_string(&str)); + if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE)) + goto exit_with_archive; - exit_rle_string(&str); + if (strcmp(stats.name, "control") != 0) + goto exit_with_archive; - status = g_type_memory_load_types(result->tpmem, pbuf); - if (!status) goto exit_while_loading; + if (stats.size < (6 + 2 + 1 + 1 + 1)) + goto exit_with_archive; - status = unpack_uleb128(&count, pbuf); + file = zip_fopen_index(archive, 0, ZIP_FL_UNCHANGED); + if (file == NULL) + { + LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive)); + goto exit_with_archive; + } - for (i = 0; i < count && status; i++) - status = g_object_storage_load_backend(result, pbuf); + data = malloc(stats.size); - exit_while_loading: + got = zip_fread(file, data, stats.size); - if (!status) + ret = zip_fclose(file); + if (ret != 0) { - g_object_unref(G_OBJECT(result)); - result = NULL; + zip_error_set(&error, ret, 0); + LOG_ERROR_ZIP("zip_fclose", &error); + goto exit_with_data; } - quick_exit: + if (got != stats.size) + goto exit_with_data; - return result; + if (memcmp(data, STORAGE_MAGIC, 6) != 0) + goto exit_with_data; -} + if (memcmp(((uint8_t *)data) + 6, STORAGE_NUMBER, 2) != 0) + goto exit_with_data; + pos = (uint8_t *)data + 8; + max = (uint8_t *)data + got; -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire de conservations à manipuler. * -* pbuf = zone tampon à remplir. [OUT] * -* * -* Description : Sauvegarde le support d'une conservation d'objets en place. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ + status = unpack_sized_binary(&storage->type, &pos, max); + if (!status) goto exit_with_data; -bool g_object_storage_store(GObjectStorage *storage, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - rle_string str; /* Chaîne à conserver */ - size_t i; /* Boucle de parcours */ + if (pos >= max) + goto exit_with_data; - result = extend_packed_buffer(pbuf, STORAGE_MAGIC STORAGE_NUMBER, 6, false); + storage->version = *(uint8_t *)pos; + pos = (uint8_t *)pos + 1; - if (result) + unpack_sized_binary_as_string(&storage->uid, &pos, max); + if (!status) goto exit_with_data; + + if (pos != max) + goto exit_with_data; + + free(data); + data = NULL; + + /* Extraction de la conservation des types */ + + ret = zip_stat_index(archive, 1, ZIP_FL_UNCHANGED, &stats); + if (ret != 0) { - init_static_rle_string(&str, storage->hash); + LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive)); + goto exit_with_archive; + } - result = pack_rle_string(&str, pbuf); + if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE)) + goto exit_with_archive; - exit_rle_string(&str); + if (strcmp(stats.name, "types") != 0) + goto exit_with_archive; + file = zip_fopen_index(archive, 1, ZIP_FL_UNCHANGED); + if (file == NULL) + { + LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive)); + goto exit_with_archive; } - g_mutex_lock(&storage->mutex); + data = malloc(stats.size); - if (result) - result = g_type_memory_store_types(storage->tpmem, pbuf); + got = zip_fread(file, data, stats.size); - if (result) - result = pack_uleb128((uleb128_t []){ storage->count }, pbuf); + ret = zip_fclose(file); + if (ret != 0) + { + zip_error_set(&error, ret, 0); + LOG_ERROR_ZIP("zip_fclose", &error); + goto exit_with_data; + } - for (i = 0; i < storage->count && result; i++) - result = pack_storage_backend(&storage->backends[i], pbuf); + asprintf(&prefix, "%s-types", storage->uid.static_data); - g_mutex_unlock(&storage->mutex); + fd = make_tmp_file(prefix, "cache", &tpmem_filename); - return result; + free(prefix); -} + if (fd == -1) + goto exit_with_data; + status = safe_write(fd, data, stats.size); + if (!status) + { + close(fd); + goto exit_with_data; + } -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* name = désignation d'un nouveau groupe d'objets. * -* * -* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. * -* * -* Retour : Informations liées à un groupe ou NULL en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ + moved = lseek(fd, 0, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + close(fd); + goto exit_with_data; + } -static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name) -{ - storage_backend_t *result; /* Encadrement à retourner */ - size_t i; /* Boucle de parcours */ + status = g_type_memory_load(storage->tpmem, fd); - assert(!g_mutex_trylock(&storage->mutex)); + close(fd); - for (i = 0; i < storage->count; i++) - if (strcmp(storage->backends[i].name, name) == 0) - break; + if (!status) + goto exit_with_data; - if (i == storage->count) - result = NULL; - else - result = &storage->backends[i]; + free(data); + data = NULL; + + /* Extraction des différents objects restants */ + + if (entries_count > 2) + { + storage->count = entries_count - 2; + storage->backends = calloc(storage->count, sizeof(storage_backend_t)); + + for (i = 2; i < entries_count; i++) + { + backend = &storage->backends[i - 2]; + + ret = zip_stat_index(archive, i, ZIP_FL_UNCHANGED, &stats); + if (ret != 0) + { + LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive)); + goto exit_with_archive; + } + + if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE)) + goto exit_with_archive; + + if (strncmp(stats.name, SL("backends/")) != 0) + goto exit_with_archive; + + slash = strchr(stats.name, '/'); + + if (slash == NULL) + goto exit_with_archive; + + if (strchr(slash + 1, '/') != NULL) + goto exit_with_archive; + + if (!g_object_storage_has_no_backend_named(storage, slash + 1)) + goto exit_with_archive; + + file = zip_fopen_index(archive, i, ZIP_FL_UNCHANGED); + if (file == NULL) + { + LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive)); + goto exit_with_archive; + } + + data = malloc(stats.size); + + got = zip_fread(file, data, stats.size); + + ret = zip_fclose(file); + if (ret != 0) + { + zip_error_set(&error, ret, 0); + LOG_ERROR_ZIP("zip_fclose", &error); + goto exit_with_data; + } + + backend->name = strdup(slash + 1); + + asprintf(&prefix, "%s-%s", storage->uid.static_data, backend->name); + + backend->fd = make_tmp_file(prefix, "cache", &backend->filename); + + free(prefix); + + if (backend->fd == -1) + goto exit_with_data; + + status = safe_write(backend->fd, data, stats.size); + if (!status) goto exit_with_data; + + moved = lseek(backend->fd, 0, SEEK_SET); + if (moved == ((off_t)-1)) + { + LOG_ERROR_N("lseek"); + goto exit_with_data; + } + + free(data); + data = NULL; + + } + + } + + /* Clôture des opérations */ + + result = storage; + ref_object(storage); + + exit_with_data: + + if (data != NULL) + free(data); + + exit_with_archive: + + ret = zip_close(archive); + + if (ret != 0) + LOG_ERROR_ZIP("zip_close", zip_get_error(archive)); + + if (tpmem_filename != NULL) + unlink(tpmem_filename); + + zip_error_fini(&error); + + exit: + + unref_object(storage); return result; @@ -380,11 +592,10 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, /****************************************************************************** * * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* name = désignation d'un nouveau groupe d'objets. * -* backend = support mis en place pour les enregistrements. * +* Paramètres : storage = gestionnaire de conservations à manipuler. * +* filename = fichier de destination à constituer. * * * -* Description : Ajoute le support d'un nouveau groupe d'objets construits. * +* Description : Sauvegarde le support d'une conservation d'objets en place. * * * * Retour : Bilan de l'opération. * * * @@ -392,46 +603,199 @@ static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, * * ******************************************************************************/ -static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend) +bool g_object_storage_store(GObjectStorage *storage, const char *filename) { bool result; /* Bilan à retourner */ + int err; /* Eventuel code d'erreur */ + zip_t *archive; /* Archive ZIP à manipuler */ + zip_error_t error; /* Suivi des erreurs obtenues */ + char *tpmem_filename; /* Chemin d'accès pour types */ + void *type_buf; /* Données pour le type */ + size_t type_buflen; /* Quantité de ces données */ + void *uid_buf; /* Données pour l'identifiant */ + size_t uid_buflen; /* Quantité de ces données */ + size_t control_len; /* Taille des premières données*/ + uint8_t *control; /* Premières données du fichier*/ + zip_source_t *zip_data; /* Données ZIP à intégrer */ + zip_int64_t index; /* Nouvel index du contenu */ + int ret; /* Bilan d'un appel */ char *prefix; /* Début de nom de fichier */ - char *filename; /* Chemin d'accès aux données */ int fd; /* Descripteur de flux ouvert */ + bool status; /* Bilan d'une écriture */ + size_t i; /* Boucle de parcours */ + char *zip_name; /* Destination pour l'archive */ result = false; - *backend = NULL; + archive = zip_open(filename, ZIP_CREATE | ZIP_TRUNCATE, &err); + if (archive == NULL) + { + zip_error_init_with_code(&error, err); + LOG_ERROR_ZIP("zip_open", &error); + goto exit; + } - assert(!g_mutex_trylock(&storage->mutex)); + zip_error_init(&error); - if (g_object_storage_find_backend(storage, name) != NULL) - goto exit; + tpmem_filename = NULL; - /* Préparatifs */ + /* Fichier de contrôle */ - asprintf(&prefix, "%s-%s", storage->hash, name); + type_buf = pack_sized_binary(&storage->type, &type_buflen); - fd = make_tmp_file(prefix, "cache", &filename); + uid_buf = pack_sized_binary_as_string(&storage->uid, &uid_buflen); + + assert((sizeof(STORAGE_MAGIC) - 1 + sizeof(STORAGE_NUMBER) - 1) == 8); + + control_len = 8 + type_buflen + 1 + uid_buflen; + control = malloc(control_len * sizeof(uint8_t)); + + memcpy(control, STORAGE_MAGIC, 6); + memcpy(control + 6, STORAGE_NUMBER, 2); + + memcpy(control + 8, type_buf, type_buflen); + + control[8 + type_buflen] = storage->version; + + memcpy(control + 8 + type_buflen + 1, uid_buf, uid_buflen); + + zip_data = zip_source_buffer_create(control, control_len, 0, &error); + if (zip_data == NULL) + { + LOG_ERROR_ZIP("zip_source_buffer_create", &error); + goto exit_with_control; + } + + index = zip_file_add(archive, "control", zip_data, ZIP_FL_ENC_UTF_8); + if (index == -1) + { + zip_source_free(zip_data); + LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive)); + goto exit_with_control; + } + + ret = zip_set_file_compression(archive, index, ZIP_CM_STORE, 0 /* comp_flags */); + if (ret == -1) + { + LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive)); + goto exit_with_control; + } + + /* Composants de la conservation */ + + g_mutex_lock(&storage->mutex); + + /* Conservation des types */ + + asprintf(&prefix, "%s-types", storage->uid.static_data); + + fd = make_tmp_file(prefix, "cache", &tpmem_filename); free(prefix); if (fd == -1) - goto exit; + goto exit_with_lock; - /* Inscription en bonne et due forme */ + status = g_type_memory_store(storage->tpmem, fd); - storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t)); + close(fd); - *backend = &storage->backends[storage->count - 1]; + if (!status) + goto exit_with_lock; - (*backend)->name = strdup(name); + zip_data = zip_source_file_create(tpmem_filename, 0, -1 /* ZIP_LENGTH_TO_END */, &error); + if (zip_data == NULL) + { + LOG_ERROR_ZIP("zip_source_file_create", &error); + goto exit_with_lock; + } - (*backend)->filename = filename; - (*backend)->fd = fd; + index = zip_file_add(archive, "types", zip_data, ZIP_FL_ENC_UTF_8); + if (index == -1) + { + zip_source_free(zip_data); + LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive)); + goto exit_with_lock; + } + + ret = zip_set_file_compression(archive, index, ZIP_CM_DEFLATE, 9 /* comp_flags */); + if (ret == -1) + { + LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive)); + goto exit_with_lock; + } + + /* Conservation des objets */ + + for (i = 0; i < storage->count; i++) + { + zip_data = zip_source_file_create(storage->backends[i].filename, 0, -1 /* ZIP_LENGTH_TO_END */, &error); + if (zip_data == NULL) + { + LOG_ERROR_ZIP("zip_source_file_create", &error); + goto exit_with_lock; + } + + /** + * Pas besoin de distinguer les chemins UNIX et Windows ici. + * + * Cf. https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT : + * + * 4.4.17 file name: (Variable) + * + * The path stored MUST NOT contain a drive or + * device letter, or a leading slash. All slashes + * MUST be forward slashes '/' as opposed to + * backwards slashes '\' for compatibility with Amiga + * and UNIX file systems etc. If input came from standard + * input, there is no file name field. + * + */ + + asprintf(&zip_name, "backends/%s", storage->backends[i].name); + + index = zip_file_add(archive, zip_name, zip_data, ZIP_FL_ENC_UTF_8); + + free(zip_name); + + if (index == -1) + { + zip_source_free(zip_data); + LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive)); + goto exit_with_lock; + } + + ret = zip_set_file_compression(archive, index, ZIP_CM_DEFLATE, 9 /* comp_flags */); + if (ret == -1) + { + LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive)); + goto exit_with_lock; + } + + } result = true; + /* Clôture des opérations */ + + exit_with_lock: + + g_mutex_unlock(&storage->mutex); + + exit_with_control: + + ret = zip_close(archive); + + if (ret != 0) + LOG_ERROR_ZIP("zip_close", zip_get_error(archive)); + + free(control); + + if (tpmem_filename != NULL) + unlink(tpmem_filename); + + zip_error_fini(&error); + exit: return result; @@ -441,71 +805,67 @@ static bool g_object_storage_add_backend(GObjectStorage *storage, const char *na /****************************************************************************** * * -* Paramètres : storage = gestionnaire de conservations à compléter. * -* pbuf = zone tampon à lire. * +* Paramètres : storage = gestionnaire de conservations à consulter. * +* name = désignation d'un nouveau groupe d'objets. * * * -* Description : Extrait d'un tampon des enregistrements spécifiques. * +* Description : Assure l'inexistence d'un groupe avec un nom donné. * * * -* Retour : Bilan de l'opération. * +* Retour : Bilan des recherches. * * * * Remarques : - * * * ******************************************************************************/ -static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer_t *pbuf) +static bool g_object_storage_has_no_backend_named(GObjectStorage *storage, const char *name) { bool result; /* Bilan à retourner */ - rle_string str; /* Chaîne à conserver */ - bool status; /* Bilan de lecture de contenu */ - storage_backend_t *backend; /* Informations à intégrer */ - uleb128_t length; /* Taille des données à charger*/ - off_t moved; /* Nouvelle position établie */ - - result = false; - - g_mutex_lock(&storage->mutex); - - /* Récupération du nom et création du support */ - - setup_empty_rle_string(&str); + size_t i; /* Boucle de parcours */ - status = unpack_rle_string(&str, pbuf); - if (!status) goto exit; + result = true; - if (get_rle_string(&str) == NULL) + for (i = 0; i < storage->count && result; i++) { - exit_rle_string(&str); - goto exit; - } - - status = g_object_storage_add_backend(storage, get_rle_string(&str), &backend); + if (storage->backends[i].name == NULL) + break; - exit_rle_string(&str); + if (strcmp(storage->backends[i].name, name) == 0) + result = false; - if (!status) goto exit; + } - /* Récupération du contenu */ + return result; - status = unpack_uleb128(&length, pbuf); - if (!status) goto exit; +} - status = safe_write(backend->fd, pbuf->data + pbuf->pos, length); - if (!status) goto exit; - advance_packed_buffer(pbuf, length); +/****************************************************************************** +* * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* name = désignation d'un nouveau groupe d'objets. * +* * +* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. * +* * +* Retour : Informations liées à un groupe ou NULL en cas d'échec. * +* * +* Remarques : - * +* * +******************************************************************************/ - moved = lseek(backend->fd, 0, SEEK_SET); - if (moved == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } +static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name) +{ + storage_backend_t *result; /* Encadrement à retourner */ + size_t i; /* Boucle de parcours */ - result = true; + assert(!g_mutex_trylock(&storage->mutex)); - exit: + for (i = 0; i < storage->count; i++) + if (strcmp(storage->backends[i].name, name) == 0) + break; - g_mutex_unlock(&storage->mutex); + if (i == storage->count) + result = NULL; + else + result = &storage->backends[i]; return result; @@ -514,10 +874,11 @@ static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer /****************************************************************************** * * -* Paramètres : backend = stockage des enregistrements spécifiques. * -* pbuf = zone tampon à remplir. [OUT] * +* Paramètres : storage = gestionnaire de conservations à compléter. * +* name = désignation d'un nouveau groupe d'objets. * +* backend = support mis en place pour les enregistrements. * * * -* Description : Place dans un tampon les données liées à des enregistrements.* +* Description : Ajoute le support d'un nouveau groupe d'objets construits. * * * * Retour : Bilan de l'opération. * * * @@ -525,72 +886,45 @@ static bool g_object_storage_load_backend(GObjectStorage *storage, packed_buffer * * ******************************************************************************/ -static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer_t *pbuf) +static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend) { bool result; /* Bilan à retourner */ - rle_string str; /* Chaîne à conserver */ - bool status; /* Bilan de lecture de contenu */ - off_t current; /* Position courante */ - off_t moved; /* Nouvelle position établie */ - void *data; /* Données à transférer */ + char *prefix; /* Début de nom de fichier */ + char *filename; /* Chemin d'accès aux données */ + int fd; /* Descripteur de flux ouvert */ result = false; - /* Inscription du nom */ + *backend = NULL; - init_static_rle_string(&str, backend->name); + assert(!g_mutex_trylock(&storage->mutex)); - status = pack_rle_string(&str, pbuf); + if (g_object_storage_find_backend(storage, name) != NULL) + goto exit; - exit_rle_string(&str); + /* Préparatifs */ - if (!status) goto exit; + asprintf(&prefix, "%s-%s", storage->uid.static_data, name); - /* Inscription du contenu */ + fd = make_tmp_file(prefix, "cache", &filename); - current = lseek(backend->fd, 0, SEEK_CUR); - if (current == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } + free(prefix); - moved = lseek(backend->fd, 0, SEEK_SET); - if (moved == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); + if (fd == -1) goto exit; - } - - data = malloc(current); - if (data == NULL) - { - LOG_ERROR_N("malloc"); - goto restore; - } - status = safe_read(backend->fd, data, current); - if (!status) goto free_mem; - - status = pack_uleb128((uleb128_t []){ current }, pbuf); - if (!status) goto free_mem; - - status = extend_packed_buffer(pbuf, data, current, false); + /* Inscription en bonne et due forme */ - free_mem: + storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t)); - free(data); + *backend = &storage->backends[storage->count - 1]; - restore: + (*backend)->name = strdup(name); - moved = lseek(backend->fd, current, SEEK_SET); - if (moved == ((off_t)-1)) - { - LOG_ERROR_N("lseek"); - goto exit; - } + (*backend)->filename = filename; + (*backend)->fd = fd; - result = status; + result = true; exit: @@ -602,7 +936,7 @@ static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer /****************************************************************************** * * * Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * +* name = désignation d'un groupe d'objets à consulter. * * pos = tête de lecture avant écriture. * * * * Description : Charge un objet à partir de données rassemblées. * @@ -613,56 +947,44 @@ static bool pack_storage_backend(const storage_backend_t *backend, packed_buffer * * ******************************************************************************/ -GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos) +static GSerializableObject *g_object_storage_load_object_unlocked(GObjectStorage *storage, const char *name, off64_t pos) { GSerializableObject *result; /* Instance à retourner */ - bool status; /* Bilan d'une opération */ storage_backend_t *backend; /* Informations à consulter */ - packed_buffer_t pbuf; /* Tampon des données à lire */ off64_t new; /* Nouvelle position de lecture*/ + bool status; /* Bilan d'une opération */ result = NULL; - /* Chargement */ - - status = false; + assert(!g_mutex_trylock(&storage->mutex)); - g_mutex_lock(&storage->mutex); + /* Chargement */ backend = g_object_storage_find_backend(storage, name); + if (backend == NULL) goto exit; - if (backend != NULL) + new = lseek64(backend->fd, pos, SEEK_SET); + if (new == (off_t)-1) { - new = lseek64(backend->fd, pos, SEEK_SET); - - if (new == pos) - { - init_packed_buffer(&pbuf); - status = read_packed_buffer(&pbuf, backend->fd); - } - + LOG_ERROR_N("lseek64"); + goto exit; } - g_mutex_unlock(&storage->mutex); - - if (!status) - goto exit; + assert (new == pos); /* Phase de conversion */ - result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object(storage->tpmem, &pbuf)); + result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object_from_gtype(storage->tpmem, backend->fd)); if (result) { - status = g_serializable_object_load(result, storage, &pbuf); + status = g_serializable_object_load(result, storage, backend->fd); if (!status) g_clear_object(&result); } - exit_packed_buffer(&pbuf); - exit: return result; @@ -673,10 +995,10 @@ GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const /****************************************************************************** * * * Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pbuf = zone tampon à parcourir. * +* name = désignation d'un groupe d'objets à consulter. * +* pos = tête de lecture avant écriture. * * * -* Description : Charge un objet interne à partir de données rassemblées. * +* Description : Charge un objet à partir de données rassemblées. * * * * Retour : Objet restauré en mémoire ou NULL en cas d'échec. * * * @@ -684,18 +1006,15 @@ GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const * * ******************************************************************************/ -GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf) +GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos) { GSerializableObject *result; /* Instance à retourner */ - uint64_t pos; /* Localisation des données */ - bool status; /* Bilan d'une opération */ - result = NULL; + g_mutex_lock(&storage->mutex); - status = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true); + result = g_object_storage_load_object_unlocked(storage, name, pos); - if (status) - result = g_object_storage_load_object(storage, name, pos); + g_mutex_unlock(&storage->mutex); return result; @@ -704,60 +1023,70 @@ GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, con /****************************************************************************** * * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pbuf = zone tampon à parcourir. * -* expected = type d'objet attendu. * -* ... = élément restauré ou NULL en cas d'échec. [OUT] * +* Paramètres : storage = gestionnaire à manipuler. * +* name = désignation d'un groupe d'objets à consulter. * +* target_name = désignation d'un second groupe d'objets ciblé. * * * -* Description : Charge un objet interne à partir de données rassemblées. * +* Description : Charge un objet interne à partir d'une référence embarquée. * * * -* Retour : Bilan de l'opération. * +* Retour : Objet restauré en mémoire ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ -bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, packed_buffer_t *pbuf, GType expected, ...) +GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, const char *name, const char *target_name) { - bool result; /* Bilan d'une opération */ - uint64_t pos; /* Localisation des données */ - GSerializableObject *instance; /* Objet rechargé à valider */ - va_list ap; /* Liste d'arguments variables */ - void **object; /* Lieu d'enregistrement final */ + GSerializableObject *result; /* Instance à retourner */ + storage_backend_t *backend; /* Informations à consulter */ + uleb128_t pos; /* Localisation des données */ + bool status; /* Bilan d'une opération */ + off64_t saved; /* Sauvegarde de position */ + off64_t new; /* Nouvelle position de lecture*/ - result = extract_packed_buffer(pbuf, &pos, sizeof(uint64_t), true); + result = NULL; - if (result) - { - if (pos == 0) - *object = NULL; + g_mutex_lock(&storage->mutex); - else - { - instance = g_object_storage_load_object(storage, name, pos); + /* Récupération de la position */ - result = G_TYPE_CHECK_INSTANCE_TYPE(instance, expected); + backend = g_object_storage_find_backend(storage, name); + if (backend == NULL) goto exit; - if (result) - { - va_start(ap, expected); + status = load_uleb128(&pos, backend->fd); + if (!status) goto exit; - object = va_arg(ap, void **); + saved = lseek64(backend->fd, 0, SEEK_CUR); + if (saved == (off_t)-1) + { + LOG_ERROR_N("lseek64"); + goto exit; + } - *object = instance; + /* Chargement */ - va_end(ap); + result = g_object_storage_load_object_unlocked(storage, target_name, pos); - } + if (result == NULL) goto exit; - else - g_clear_object(&instance); + /* Restauration de la position courante */ - } + new = lseek64(backend->fd, saved, SEEK_SET); + if (new == (off_t)-1) + { + LOG_ERROR_N("lseek64"); + + g_clear_object(&result); + goto exit; } + assert (new == saved); + + exit: + + g_mutex_unlock(&storage->mutex); + return result; } @@ -766,7 +1095,7 @@ bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, /****************************************************************************** * * * Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * +* name = désignation d'un groupe d'objets, nouveau ou non. * * object = objet sérialisable à traiter. * * pos = tête de lecture avant écriture. [OUT] * * * @@ -781,22 +1110,9 @@ bool g_object_storage_unpack_object_2(GObjectStorage *storage, const char *name, bool g_object_storage_store_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, off64_t *pos) { bool result; /* Bilan à retourner */ - packed_buffer_t pbuf; /* Tampon des données à écrire */ storage_backend_t *backend; /* Informations à consulter */ off64_t tmp; /* Conservation éphémère */ - /* Phase de conversion */ - - init_packed_buffer(&pbuf); - - result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), &pbuf); - if (!result) goto exit; - - result = g_serializable_object_store(object, storage, &pbuf); - if (!result) goto exit; - - /* Enregistrement */ - result = false; g_mutex_lock(&storage->mutex); @@ -814,54 +1130,18 @@ bool g_object_storage_store_object(GObjectStorage *storage, const char *name, co *pos = lseek64(backend->fd, 0, SEEK_CUR); if (*pos != (off64_t)-1) - result = write_packed_buffer(&pbuf, backend->fd); - - } - - g_mutex_unlock(&storage->mutex); - - /* Sortie propre */ - - exit: - - exit_packed_buffer(&pbuf); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : storage = gestionnaire à manipuler. * -* name = désignation d'un nouveau groupe d'objets. * -* pbuf = zone tampon à remplir. * -* * -* Description : Sauvegarde un object interne sous forme de données. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_object_storage_pack_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, packed_buffer_t *pbuf) -{ - bool result; /* Bilan à retourner */ - off64_t pos; /* Localisation des données */ - - if (object == NULL) - result = extend_packed_buffer(pbuf, (uint64_t []){ 0 }, sizeof(uint64_t), true); + { + result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), backend->fd); - else - { - result = g_object_storage_store_object(storage, name, object, &pos); + if (result) + result = g_serializable_object_store(object, storage, backend->fd); - if (result) - result = extend_packed_buffer(pbuf, (uint64_t []){ pos }, sizeof(uint64_t), true); + } } + g_mutex_unlock(&storage->mutex); + return result; } diff --git a/src/glibext/storage.h b/src/glibext/storage.h index cc0caad..8231a31 100644 --- a/src/glibext/storage.h +++ b/src/glibext/storage.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * storage.h - prototypes pour la conservation sur disque d'objets construits * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,69 +21,61 @@ */ -#ifndef _ANALYSIS_STORAGE_STORAGE_H -#define _ANALYSIS_STORAGE_STORAGE_H +#ifndef _GLIBEXT_STORAGE_H +#define _GLIBEXT_STORAGE_H -#include <glib-object.h> -#include <stdbool.h> +#include <stdint.h> +#include "helpers.h" #include "serialize.h" -#include "tpmem.h" -#define G_TYPE_OBJECT_STORAGE g_object_storage_get_type() -#define G_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_OBJECT_STORAGE, GObjectStorage)) -#define G_IS_OBJECT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_OBJECT_STORAGE)) -#define G_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_OBJECT_STORAGE, GObjectStorageClass)) -#define G_IS_OBJECT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_OBJECT_STORAGE)) -#define G_OBJECT_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_OBJECT_STORAGE, GObjectStorageClass)) +#define G_TYPE_OBJECT_STORAGE (g_object_storage_get_type()) +DECLARE_GTYPE(GObjectStorage, g_object_storage, G, OBJECT_STORAGE); -/* Définition d'une conservation d'objets construits (instance) */ -typedef struct _GObjectStorage GObjectStorage; - -/* Définition d'une conservation d'objets construits (classe) */ -typedef struct _GObjectStorageClass GObjectStorageClass; - - -/* Indique le type défini pour une conservation d'objets construits. */ -GType g_object_storage_get_type(void); /* Crée le support d'une conservation d'objets en place. */ -GObjectStorage *g_object_storage_new(const char *); - -#define get_storage_linked_format(s) \ - ({ \ - void*__result; \ - __result = g_object_get_data(G_OBJECT(s), "format"); \ - g_object_ref(G_OBJECT(__result)); \ - __result; \ - }) +GObjectStorage *g_object_storage_new(const char *, uint8_t, const char *); /* Charge le support d'une conservation d'objets en place. */ -GObjectStorage *g_object_storage_load(packed_buffer_t *); +GObjectStorage *g_object_storage_load(const char *); /* Sauvegarde le support d'une conservation d'objets en place. */ -bool g_object_storage_store(GObjectStorage *, packed_buffer_t *); +bool g_object_storage_store(GObjectStorage *, const char *); /* Charge un objet à partir de données rassemblées. */ GSerializableObject *g_object_storage_load_object(GObjectStorage *, const char *, off64_t); -/* Charge un objet interne à partir de données rassemblées. */ -GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, const char *, packed_buffer_t *); +/* Charge un objet interne à partir d'une référence embarquée. */ +GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, const char *, const char *); /* Sauvegarde un object sous forme de données rassemblées. */ bool g_object_storage_store_object(GObjectStorage *, const char *, const GSerializableObject *, off64_t *); -/* Charge un objet interne à partir de données rassemblées. */ -bool g_object_storage_unpack_object_2(GObjectStorage *, const char *, packed_buffer_t *, GType, ...); -/* Sauvegarde un object interne sous forme de données. */ -bool g_object_storage_pack_object(GObjectStorage *, const char *, const GSerializableObject *, packed_buffer_t *); + + +#if 0 + +/** + * TODO : REMME ? + */ + +#define get_storage_linked_format(s) \ + ({ \ + void*__result; \ + __result = g_object_get_data(G_OBJECT(s), "format"); \ + g_object_ref(G_OBJECT(__result)); \ + __result; \ + }) + +#endif + -#endif /* _ANALYSIS_STORAGE_STORAGE_H */ +#endif /* _GLIBEXT_STORAGE_H */ diff --git a/src/glibext/tpmem-int.h b/src/glibext/tpmem-int.h new file mode 100644 index 0000000..b1b7eec --- /dev/null +++ b/src/glibext/tpmem-int.h @@ -0,0 +1,78 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * tpmem-int.h - définitions internes propres à la mémorisation des types d'objets mis en cache + * + * Copyright (C) 2020-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 _GLIBEXT_TPMEM_INT_H +#define _GLIBEXT_TPMEM_INT_H + + +#include "tpmem.h" + + +/* Conservation d'une référence sur un type */ +typedef struct _gtype_ref_info_t +{ + GType gtype; /* Type pour la GLib */ + gpointer gclass; /* Lien vers sa classe */ + + /** + * La GLib n'est pas très claire sur la taille de GType comme le montre le + * code issu de <sources>/gobject/gtype.h : + * + * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus + * typedef gsize GType; + * #else // for historic reasons, C++ links against gulong GTypes + * typedef gulong GType; + * #endif + * + * Et : + * + * typedef unsigned $glib_size_type_define gsize; + * + * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits + * lors des enregistrements. + */ + +} gtype_ref_info_t; + + +/* Définition d'une mémoire de types d'objets (instance) */ +struct _GTypeMemory +{ + GObject parent; /* A laisser en premier */ + + gtype_ref_info_t *gtypes; /* Types des objets reconnus */ + size_t count; /* Quantité de ces objets */ + GMutex mutex; /* Contrôle d'accès à la liste */ + +}; + +/* Définition d'une mémoire de types d'objets (classe) */ +struct _GTypeMemoryClass +{ + GObjectClass parent; /* A laisser en premier */ + +}; + + + +#endif /* _GLIBEXT_TPMEM_INT_H */ diff --git a/src/glibext/tpmem.c b/src/glibext/tpmem.c index 0703aeb..14b5e33 100644 --- a/src/glibext/tpmem.c +++ b/src/glibext/tpmem.c @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * tpmem.c - mémorisation des types d'objets mis en cache * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -25,59 +25,14 @@ #include <assert.h> -#include <stdint.h> -#include "../db/misc/rlestr.h" -#include "../../arch/operands/target.h" -#include "../../core/logs.h" +#include "tpmem-int.h" +#include "../common/szbin.h" +#include "../core/logs.h" -/* Conservation d'une référence sur un type */ -typedef struct _gtype_ref_info_t -{ - GType gtype; /* Type pour la GLib */ - gpointer gclass; /* Lien vers sa classe */ - - /** - * La GLib n'est pas très claire sur la taille de GType : - * - * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus - * typedef gsize GType; - * #else // for historic reasons, C++ links against gulong GTypes - * typedef gulong GType; - * #endif - * - * Et : - * - * typedef unsigned $glib_size_type_define gsize; - * - * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits - * lors des enregistrements. - */ - -} gtype_ref_info_t; - -/* Définition d'une mémoire de types d'objets (instance) */ -struct _GTypeMemory -{ - GObject parent; /* A laisser en premier */ - - gtype_ref_info_t *gtypes; /* Types des objets reconnus */ - size_t count; /* Quantité de ces objets */ - GMutex mutex; /* Contrôle d'accès à la liste */ - -}; - -/* Définition d'une mémoire de types d'objets (classe) */ -struct _GTypeMemoryClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - /* Initialise la classe des mémoires de types d'objets. */ static void g_type_memory_class_init(GTypeMemoryClass *); @@ -85,10 +40,10 @@ static void g_type_memory_class_init(GTypeMemoryClass *); static void g_type_memory_init(GTypeMemory *); /* Supprime toutes les références externes. */ -static void g_type_memory_dispose(GTypeMemory *); +static void g_type_memory_dispose(GObject *); /* Procède à la libération totale de la mémoire. */ -static void g_type_memory_finalize(GTypeMemory *); +static void g_type_memory_finalize(GObject *); @@ -114,8 +69,8 @@ static void g_type_memory_class_init(GTypeMemoryClass *klass) object = G_OBJECT_CLASS(klass); - object->dispose = (GObjectFinalizeFunc/* ! */)g_type_memory_dispose; - object->finalize = (GObjectFinalizeFunc)g_type_memory_finalize; + object->dispose = g_type_memory_dispose; + object->finalize = g_type_memory_finalize; } @@ -143,7 +98,7 @@ static void g_type_memory_init(GTypeMemory *tpmem) /****************************************************************************** * * -* Paramètres : tpmem = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -153,10 +108,13 @@ static void g_type_memory_init(GTypeMemory *tpmem) * * ******************************************************************************/ -static void g_type_memory_dispose(GTypeMemory *tpmem) +static void g_type_memory_dispose(GObject *object) { + GTypeMemory *tpmem; /* Version spécialisée */ uint64_t i; /* Boucle de parcours */ + tpmem = G_TYPE_MEMORY(object); + g_mutex_lock(&tpmem->mutex); for (i = 0; i < tpmem->count; i++) @@ -167,14 +125,14 @@ static void g_type_memory_dispose(GTypeMemory *tpmem) g_mutex_clear(&tpmem->mutex); - G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(G_OBJECT(tpmem)); + G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(object); } /****************************************************************************** * * -* Paramètres : tpmem = instance d'objet GLib à traiter. * +* Paramètres : object = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -184,12 +142,16 @@ static void g_type_memory_dispose(GTypeMemory *tpmem) * * ******************************************************************************/ -static void g_type_memory_finalize(GTypeMemory *tpmem) +static void g_type_memory_finalize(GObject *object) { + GTypeMemory *tpmem; /* Version spécialisée */ + + tpmem = G_TYPE_MEMORY(object); + if (tpmem->gtypes != NULL) free(tpmem->gtypes); - G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(G_OBJECT(tpmem)); + G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(object); } @@ -220,7 +182,7 @@ GTypeMemory *g_type_memory_new(void) /****************************************************************************** * * * Paramètres : tpmem = mémoire à compléter. * -* pbuf = zone tampon à lire. * +* fd = flux ouvert en lecture. * * * * Description : Apprend tous les types mémorisés dans un tampon. * * * @@ -230,14 +192,14 @@ GTypeMemory *g_type_memory_new(void) * * ******************************************************************************/ -bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) +bool g_type_memory_load(GTypeMemory *tpmem, int fd) { bool result; /* Bilan à enregistrer */ uleb128_t count; /* Nombre d'éléments détectés */ uleb128_t i; /* Boucle de parcours */ - rle_string str; /* Chaîne à charger */ + sized_binary_t str; /* Chaîne à charger */ - result = unpack_uleb128(&count, pbuf); + result = load_uleb128(&count, fd); if (result) { @@ -248,35 +210,27 @@ bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) assert(tpmem->gtypes == NULL); tpmem->gtypes = calloc(count, sizeof(gtype_ref_info_t)); - setup_empty_rle_string(&str); - for (i = 0; i < tpmem->count && result; i++) { - result = unpack_rle_string(&str, pbuf); + result = load_sized_binary_as_string(&str, fd); if (!result) break; - if (get_rle_string(&str) == NULL) - { - exit_rle_string(&str); - break; - } - - tpmem->gtypes[i].gtype = g_type_from_name(get_rle_string(&str)); + tpmem->gtypes[i].gtype = g_type_from_name(str.data); result = (tpmem->gtypes[i].gtype != 0); if (!result) - log_variadic_message(LMT_ERROR, "Unknown type: '%s'", get_rle_string(&str)); + log_variadic_message(LMT_ERROR, "Unknown type: '%s'", str.data); else tpmem->gtypes[i].gclass = g_type_class_ref(tpmem->gtypes[i].gtype); - exit_rle_string(&str); + exit_sized_binary(&str); } - } + g_mutex_unlock(&tpmem->mutex); - g_mutex_unlock(&tpmem->mutex); + } return result; @@ -285,38 +239,40 @@ bool g_type_memory_load_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) /****************************************************************************** * * -* Paramètres : tpmem = mémoire à manipuler. * -* pbuf = zone tampon à venir lire. * +* Paramètres : tpmem = mémoire à consulter. * +* fd = flux ouvert en écriture. * * * -* Description : Crée une nouvelle instance d'objet à partir de son type. * +* Description : Enregistre tous les types mémorisés dans un tampon. * * * -* Retour : Instance issue de l'opération ou NULL. * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf) +bool g_type_memory_store(GTypeMemory *tpmem, int fd) { - GObject *result; /* Nouvelle instance à renvoyer*/ - uleb128_t index; /* Indice du point d'insertion */ - bool status; /* Bilan d'une récupération */ + bool result; /* Bilan à enregistrer */ + uint64_t i; /* Boucle de parcours */ + const gchar *name; /* Désignation d'un type */ + sized_binary_t str; /* Chaîne à conserver */ - result = NULL; + g_mutex_lock(&tpmem->mutex); - status = unpack_uleb128(&index, pbuf); + result = store_uleb128((uleb128_t []){ tpmem->count }, fd); - if (status) + for (i = 0; i < tpmem->count && result; i++) { - g_mutex_lock(&tpmem->mutex); + name = g_type_name(tpmem->gtypes[i].gtype); - if (index < tpmem->count) - result = g_object_new(tpmem->gtypes[index].gtype, NULL); + setup_sized_binary_from_static_string(&str, name); - g_mutex_unlock(&tpmem->mutex); + store_sized_binary_as_string(&str, fd); } + g_mutex_unlock(&tpmem->mutex); + return result; } @@ -325,60 +281,35 @@ GObject *g_type_memory_create_object(GTypeMemory *tpmem, packed_buffer_t *pbuf) /****************************************************************************** * * * Paramètres : tpmem = mémoire à manipuler. * -* obj = instance dont le type est à mémoriser. * -* pbuf = zone tampon à remplir. [OUT] * +* fd = flux ouvert en lecture. * * * -* Description : Sauvegarde le type d'un objet instancié. * +* Description : Crée une nouvelle instance d'objet à partir de son type. * * * -* Retour : Bilan de l'opération. * +* Retour : Instance issue de l'opération ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_buffer_t *pbuf) +GObject *g_type_memory_create_object_from_gtype(GTypeMemory *tpmem, int fd) { - bool result; /* Bilan à retourner */ - GType gtype; /* Type à enregistrer */ - size_t index; /* Indice du point d'insertion */ - - gtype = G_TYPE_FROM_INSTANCE(obj); + GObject *result; /* Nouvelle instance à renvoyer*/ + uleb128_t index; /* Indice du point d'insertion */ + bool status; /* Bilan d'une récupération */ - /** - * Pour quelques explications sur l'esquive suivante, se rapporter aux - * commentaires de g_target_operand_unserialize(). - * - * Dans la situation présente, on ne doit pas enregistrer le type dans le tampon, - * car l'opérande va relancer l'opération entière (avec un opérande temporaire), - * ce qui conduirait à l'enregistrement de deux types successifs dans les données. - */ + result = NULL; - if (gtype == G_TYPE_TARGET_OPERAND) - result = true; + status = load_uleb128(&index, fd); - else + if (status) { g_mutex_lock(&tpmem->mutex); - for (index = 0; index < tpmem->count; index++) - if (tpmem->gtypes[index].gtype == gtype) - break; - - if (index == tpmem->count) - { - tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t)); - - assert(tpmem->count > 0); - - tpmem->gtypes[index].gtype = gtype; - tpmem->gtypes[index].gclass = g_type_class_ref(gtype); - - } + if (index < tpmem->count) + result = g_object_new(tpmem->gtypes[index].gtype, NULL); g_mutex_unlock(&tpmem->mutex); - result = pack_uleb128((uleb128_t []){ index }, pbuf); - } return result; @@ -388,10 +319,11 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b /****************************************************************************** * * -* Paramètres : tpmem = mémoire à consulter. * -* pbuf = zone tampon à remplir. [OUT] * +* Paramètres : tpmem = mémoire à manipuler. * +* obj = instance dont le type est à mémoriser. * +* fd = flux ouvert en écriture. * * * -* Description : Enregistre tous les types mémorisés dans un tampon. * +* Description : Sauvegarde le type d'un objet instancié. * * * * Retour : Bilan de l'opération. * * * @@ -399,31 +331,33 @@ bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, packed_b * * ******************************************************************************/ -bool g_type_memory_store_types(GTypeMemory *tpmem, packed_buffer_t *pbuf) +bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, int fd) { - bool result; /* Bilan à enregistrer */ - uint64_t i; /* Boucle de parcours */ - const gchar *name; /* Désignation d'un type */ - rle_string str; /* Chaîne à conserver */ + bool result; /* Bilan à retourner */ + GType gtype; /* Type à enregistrer */ + size_t index; /* Indice du point d'insertion */ + + gtype = G_TYPE_FROM_INSTANCE(obj); g_mutex_lock(&tpmem->mutex); - result = pack_uleb128((uleb128_t []){ tpmem->count }, pbuf); + for (index = 0; index < tpmem->count; index++) + if (tpmem->gtypes[index].gtype == gtype) + break; - for (i = 0; i < tpmem->count && result; i++) + if (index == tpmem->count) { - name = g_type_name(tpmem->gtypes[i].gtype); - - init_static_rle_string(&str, name); + tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t)); - result = pack_rle_string(&str, pbuf); - - exit_rle_string(&str); + tpmem->gtypes[index].gtype = gtype; + tpmem->gtypes[index].gclass = g_type_class_ref(gtype); } g_mutex_unlock(&tpmem->mutex); + result = store_uleb128((uleb128_t []){ index }, fd); + return result; } diff --git a/src/glibext/tpmem.h b/src/glibext/tpmem.h index 34cbde6..ccb8323 100644 --- a/src/glibext/tpmem.h +++ b/src/glibext/tpmem.h @@ -2,7 +2,7 @@ /* Chrysalide - Outil d'analyse de fichiers binaires * tpmem.h - prototypes pour la mémorisation des types d'objets mis en cache * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2025 Cyrille Bagard * * This file is part of Chrysalide. * @@ -21,50 +21,37 @@ */ -#ifndef _ANALYSIS_STORAGE_TPMEM_H -#define _ANALYSIS_STORAGE_TPMEM_H +#ifndef _GLIBEXT_TPMEM_H +#define _GLIBEXT_TPMEM_H -#include <glib-object.h> +#include <stdbool.h> -#include "../../common/packed.h" +#include "helpers.h" -#define G_TYPE_TYPE_MEMORY g_type_memory_get_type() -#define G_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_TYPE_MEMORY, GTypeMemory)) -#define G_IS_TYPE_MEMORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_TYPE_MEMORY)) -#define G_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_TYPE_MEMORY, GTypeMemoryClass)) -#define G_IS_TYPE_MEMORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_TYPE_MEMORY)) -#define G_TYPE_MEMORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_TYPE_MEMORY, GTypeMemoryClass)) +#define G_TYPE_TYPE_MEMORY (g_type_memory_get_type()) +DECLARE_GTYPE(GTypeMemory, g_type_memory, G, TYPE_MEMORY); -/* Définition d'une mémoire de types d'objets (instance) */ -typedef struct _GTypeMemory GTypeMemory; - -/* Définition d'une mémoire de types d'objets (classe) */ -typedef struct _GTypeMemoryClass GTypeMemoryClass; - - -/* Indique le type défini pour une mémoire de types d'objets. */ -GType g_type_memory_get_type(void); /* Crée une mémoire pour types d'objets. */ GTypeMemory *g_type_memory_new(void); /* Apprend tous les types mémorisés dans un tampon. */ -bool g_type_memory_load_types(GTypeMemory *, packed_buffer_t *); +bool g_type_memory_load(GTypeMemory *, int); + +/* Enregistre tous les types mémorisés dans un tampon. */ +bool g_type_memory_store(GTypeMemory *, int); /* Crée une nouvelle instance d'objet à partir de son type. */ -GObject *g_type_memory_create_object(GTypeMemory *, packed_buffer_t *); +GObject *g_type_memory_create_object_from_gtype(GTypeMemory *, int); /* Sauvegarde le type d'un objet instancié. */ -bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, packed_buffer_t *); - -/* Enregistre tous les types mémorisés dans un tampon. */ -bool g_type_memory_store_types(GTypeMemory *, packed_buffer_t *); +bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, int); -#endif /* _ANALYSIS_STORAGE_TPMEM_H */ +#endif /* _GLIBEXT_TPMEM_H */ |