From 802e8d68991e6644486ff14882c5c441e44117e6 Mon Sep 17 00:00:00 2001
From: Cyrille Bagard <nocbos@gmail.com>
Date: Sun, 1 Aug 2021 22:41:42 +0200
Subject: Build archive temporary filenames from one place.

---
 src/analysis/db/cdb.c      | 63 ++++++++++++++++++++++-------
 src/analysis/db/cdb.h      |  3 ++
 src/analysis/db/snapshot.c | 99 +++++++++++++++++-----------------------------
 src/analysis/db/snapshot.h |  9 +++--
 4 files changed, 94 insertions(+), 80 deletions(-)

diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c
index e4179d3..62de6a7 100644
--- a/src/analysis/db/cdb.c
+++ b/src/analysis/db/cdb.c
@@ -366,11 +366,8 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl
     if (!mkpath(tmpdir))
         goto error;
 
-    ret = asprintf(&result->xml_desc, "%s" G_DIR_SEPARATOR_S "%s_desc.xml", tmpdir, get_rle_string(hash));
-    if (ret == -1) goto no_tmp;
-
-    ret = ensure_path_exists(result->xml_desc);
-    if (ret == -1) goto no_tmp;
+    result->xml_desc = g_cdb_archive_get_tmp_filename(result, "desc.xml");
+    if (result->xml_desc == NULL) goto no_tmp;
 
     /* Création de l'archive si elle n'existe pas */
 
@@ -381,7 +378,7 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl
         /* Le soucis ne vient pas de l'absence du fichier... */
         if (errno != ENOENT) goto error;
 
-        result->snapshot = g_db_snapshot_new_empty(tmpdir, get_rle_string(hash), result->collections);
+        result->snapshot = g_db_snapshot_new_empty(result, result->collections);
 
         if (result->snapshot == NULL)
             goto error;
@@ -452,6 +449,47 @@ GCdbArchive *g_cdb_archive_new(const char *basedir, const char *tmpdir, const rl
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : archive = informations quant à l'archive à interpréter.      *
+*                suffix  = fin du nom de fichier à définir.                   *
+*                                                                             *
+*  Description : Construit un chemin pour un fichier propre à l'archive.      *
+*                                                                             *
+*  Retour      : Chemin de fichier à utiliser ou NULL en cas d'erreur.        *
+*                                                                             *
+*  Remarques   : -                                                            *
+*                                                                             *
+******************************************************************************/
+
+char *g_cdb_archive_get_tmp_filename(const GCdbArchive *archive, const char *suffix)
+{
+    char *result;                           /* Chemin à retourner          */
+    int ret;                                /* Retour d'un appel           */
+
+    ret = asprintf(&result, "%s" G_DIR_SEPARATOR_S "%s_%s",
+                   archive->tmpdir, get_rle_string(&archive->hash), suffix);
+
+    if (ret == -1)
+        result = NULL;
+
+    else
+    {
+        ret = ensure_path_exists(result);
+
+        if (ret == -1)
+        {
+            free(result);
+            result = NULL;
+        }
+
+    }
+
+    return result;
+
+}
+
+
+/******************************************************************************
+*                                                                             *
+*  Paramètres  : archive = informations quant à l'archive à interpréter.      *
 *                                                                             *
 *  Description : Ouvre une archive avec tous les éléments à conserver.        *
 *                                                                             *
@@ -501,8 +539,7 @@ static DBError g_cdb_archive_read(GCdbArchive *archive)
                 goto load_error;
             }
 
-            archive->snapshot = g_db_snapshot_new_from_xml(archive->tmpdir, get_rle_string(&archive->hash),
-                                                           xdoc, context);
+            archive->snapshot = g_db_snapshot_new_from_xml(archive, xdoc, context);
 
             close_xml_file(xdoc, context);
 
@@ -529,7 +566,7 @@ static DBError g_cdb_archive_read(GCdbArchive *archive)
     ret = archive_read_open_filename(in, archive->filename, 10240 /* ?! */);
     if (ret != ARCHIVE_OK) goto bad_archive;
 
-    status = g_db_snapshot_fill(archive->snapshot, in);
+    status = g_db_snapshot_fill(archive->snapshot, in, archive);
     if (!status) goto load_error;
 
     result = DBE_NONE;
@@ -1144,7 +1181,7 @@ static void *g_cdb_archive_process(GCdbArchive *archive)
 
                     case DBC_CREATE_SNAPSHOT:
 
-                        error = g_db_snapshot_create(archive->snapshot, archive->db);
+                        error = g_db_snapshot_create(archive->snapshot, archive->db, archive);
 
                         if (error == DBE_NONE)
                         {
@@ -1548,7 +1585,6 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_
     GObjectStorage *storage;                /* Gestionnaire de stockage    */
     GSerializableObject *content;           /* Contenu restitué            */
     const gchar *hash;                      /* Empreinte de ce contenu     */
-    int ret;                                /* Retour d'un appel           */
     int fd;                                 /* Flux ouvert en écriture     */
     bool status;                            /* Bilan d'une écriture        */
 
@@ -1615,9 +1651,8 @@ static bool g_cdb_archive_set_content(GCdbArchive *archive, packed_buffer_t *in_
         if (archive->cnt_file != NULL)
             free(archive->cnt_file);
 
-        ret = asprintf(&archive->cnt_file, "%s" G_DIR_SEPARATOR_S "%s_storedcontent.bin",
-                       archive->tmpdir, get_rle_string(&archive->hash));
-        if (ret == -1)
+        archive->cnt_file = g_cdb_archive_get_tmp_filename(archive, "storedcontent.bin");
+        if (archive->cnt_file == NULL)
         {
             error = DBE_SYS_ERROR;
             goto save_error;
diff --git a/src/analysis/db/cdb.h b/src/analysis/db/cdb.h
index 2dd8118..b2c3fc3 100644
--- a/src/analysis/db/cdb.h
+++ b/src/analysis/db/cdb.h
@@ -56,6 +56,9 @@ GType g_cdb_archive_get_type(void);
 /* Prépare un client pour une connexion à une BD. */
 GCdbArchive *g_cdb_archive_new(const char *, const char *, const rle_string *, DBError *);
 
+/* Construit un chemin pour un fichier propre à l'archive. */
+char *g_cdb_archive_get_tmp_filename(const GCdbArchive *, const char *);
+
 /* Enregistre une archive avec tous les éléments à conserver. */
 DBError g_cdb_archive_write(const GCdbArchive *);
 
diff --git a/src/analysis/db/snapshot.c b/src/analysis/db/snapshot.c
index 1a92a34..170cab5 100644
--- a/src/analysis/db/snapshot.c
+++ b/src/analysis/db/snapshot.c
@@ -37,7 +37,6 @@
 #include "collection.h"
 #include "../../common/compression.h"
 #include "../../common/extstr.h"
-#include "../../common/io.h"
 #include "../../common/sqlite.h"
 #include "../../common/xml.h"
 #include "../../core/logs.h"
@@ -69,7 +68,7 @@ static snapshot_node_t *create_snapshot_node(const char *, uint64_t, const char
 static void destroy_snapshot_node(snapshot_node_t *);
 
 /* Définit le chemin vers une base de données pour un noeud. */
-static bool setup_snapshot_node_db_path(snapshot_node_t *, const char *, const char *);
+static bool setup_snapshot_node_db_path(snapshot_node_t *, const GCdbArchive *);
 
 /* Valide la présence d'une base de données pour chaque noeud. */
 static bool check_snapshot_nodes(const snapshot_node_t *);
@@ -102,9 +101,6 @@ struct _GDbSnapshot
 {
     GObject parent;                         /* A laisser en premier        */
 
-    char *tmpdir;                           /* Répertoire de travail       */
-    char *hash;                             /* Empreinte de binaire        */
-
     snapshot_node_t *nodes;                 /* Instantanés présents        */
     snapshot_node_t *current;               /* Instantané courant          */
 
@@ -133,7 +129,7 @@ static void g_db_snapshot_dispose(GDbSnapshot *);
 static void g_db_snapshot_finalize(GDbSnapshot *);
 
 /* Prépare un gestionnaire d'instantanés de bases de données. */
-static GDbSnapshot *g_db_snapshot_new(const char *, const char *);
+static GDbSnapshot *g_db_snapshot_new(const GCdbArchive *);
 
 
 
@@ -231,9 +227,8 @@ static void destroy_snapshot_node(snapshot_node_t *node)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : node   = noeud d'instantané à traiter.                       *
-*                tmpdir = répertoire de travail temporaire.                   *
-*                hash   = empreinte du binaire à représenter.                 *
+*  Paramètres  : node    = noeud d'instantané à traiter.                      *
+*                archive = archive concernée par l'instantané.                *
 *                                                                             *
 *  Description : Définit le chemin vers une base de données pour un noeud.    *
 *                                                                             *
@@ -243,23 +238,26 @@ static void destroy_snapshot_node(snapshot_node_t *node)
 *                                                                             *
 ******************************************************************************/
 
-static bool setup_snapshot_node_db_path(snapshot_node_t *node, const char *tmpdir, const char *hash)
+static bool setup_snapshot_node_db_path(snapshot_node_t *node, const GCdbArchive *archive)
 {
     bool result;                            /* Bilan à retourner           */
     snapshot_id_t *id;                      /* Identifiant attribué        */
+    char *suffix;                           /* Fin du fichier temporaire   */
     int ret;                                /* Bilan d'une génération      */
 
     id = get_snapshot_info_id(&node->info);
 
-    ret = asprintf(&node->path, "%s" G_DIR_SEPARATOR_S "%s_%s_db.sql",
-                   tmpdir, hash, snapshot_id_as_string(id));
-
+    ret = asprintf(&suffix, "%s_db.sql", snapshot_id_as_string(id));
     result = (ret > 0);
 
     if (result)
     {
-        ret = ensure_path_exists(node->path);
-        result = (ret != -1);
+        node->path = g_cdb_archive_get_tmp_filename(archive, suffix);
+
+        free(suffix);
+
+        result = (node->path != NULL);
+
     }
 
     return result;
@@ -702,9 +700,6 @@ static void g_db_snapshot_class_init(GDbSnapshotClass *klass)
 
 static void g_db_snapshot_init(GDbSnapshot *snap)
 {
-    snap->tmpdir = NULL;
-    snap->hash = NULL;
-
     snap->nodes = NULL;
     snap->current = NULL;
 
@@ -746,12 +741,6 @@ static void g_db_snapshot_dispose(GDbSnapshot *snap)
 
 static void g_db_snapshot_finalize(GDbSnapshot *snap)
 {
-    if (snap->tmpdir != NULL)
-        free(snap->tmpdir);
-
-    if (snap->hash != NULL)
-        free(snap->hash);
-
     if (snap->nodes != NULL)
         destroy_snapshot_node(snap->nodes);
 
@@ -765,8 +754,7 @@ static void g_db_snapshot_finalize(GDbSnapshot *snap)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : tmpdir = répertoire de travail temporaire.                   *
-*                hash   = empreinte du binaire à représenter.                 *
+*  Paramètres  : archive = archive associée à l'instantané.                   *
 *                                                                             *
 *  Description : Prépare un gestionnaire d'instantanés de bases de données.   *
 *                                                                             *
@@ -776,28 +764,15 @@ static void g_db_snapshot_finalize(GDbSnapshot *snap)
 *                                                                             *
 ******************************************************************************/
 
-static GDbSnapshot *g_db_snapshot_new(const char *tmpdir, const char *hash)
+static GDbSnapshot *g_db_snapshot_new(const GCdbArchive *archive)
 {
     GDbSnapshot *result;                    /* Adresse à retourner         */
-    int ret;                                /* Bilan d'une génération      */
-    bool status;                            /* Bilan de la création        */
 
     result = g_object_new(G_TYPE_DB_SNAPSHOT, NULL);
 
-    result->tmpdir = strdup(tmpdir);
-    result->hash = strdup(hash);
+    result->current_db = g_cdb_archive_get_tmp_filename(archive, "current_db.sql");
 
-    ret = asprintf(&result->current_db, "%s" G_DIR_SEPARATOR_S "%s_current_db.sql", tmpdir, hash);
-
-    status = (ret > 0);
-
-    if (status)
-    {
-        ret = ensure_path_exists(result->current_db);
-        status = (ret != -1);
-    }
-
-    if (!status)
+    if (result->current_db == NULL)
     {
         g_object_unref(G_OBJECT(result));
         result = NULL;
@@ -810,8 +785,7 @@ static GDbSnapshot *g_db_snapshot_new(const char *tmpdir, const char *hash)
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : tmpdir      = répertoire de travail temporaire.              *
-*                hash        = empreinte du binaire à représenter.            *
+*  Paramètres  : archive     = archive associée à l'instantané.               *
 *                collections = ensemble de modifications par catégories.      *
 *                                                                             *
 *  Description : Prépare un gestionnaire d'instantanés de bases de données.   *
@@ -822,7 +796,7 @@ static GDbSnapshot *g_db_snapshot_new(const char *tmpdir, const char *hash)
 *                                                                             *
 ******************************************************************************/
 
-GDbSnapshot *g_db_snapshot_new_empty(const char *tmpdir, const char *hash, GList *collections)
+GDbSnapshot *g_db_snapshot_new_empty(const GCdbArchive *archive, GList *collections)
 {
     GDbSnapshot *result;                    /* Adresse à retourner         */
     sqlite3 *db;                            /* Base de données à manipuler */
@@ -831,12 +805,12 @@ GDbSnapshot *g_db_snapshot_new_empty(const char *tmpdir, const char *hash, GList
     GList *iter;                            /* Boucle de parcours          */
     GDbCollection *collec;                  /* Collection visée manipulée  */
 
-    result = g_db_snapshot_new(tmpdir, hash);
+    result = g_db_snapshot_new(archive);
     if (result == NULL) goto exit;
 
     result->nodes = create_snapshot_node(NULL, 0, NULL, NULL);
 
-    status = setup_snapshot_node_db_path(result->nodes, tmpdir, hash);
+    status = setup_snapshot_node_db_path(result->nodes, archive);
     if (!status) goto error;
 
     result->current = result->nodes;
@@ -886,8 +860,7 @@ GDbSnapshot *g_db_snapshot_new_empty(const char *tmpdir, const char *hash, GList
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : tmpdir  = répertoire de travail temporaire.                  *
-*                hash    = empreinte du binaire à représenter.                *
+*  Paramètres  : archive = archive associée à l'instantané.                   *
 *                xdoc    = document XML à compléter.                          *
 *                context = contexte pour les recherches.                      *
 *                                                                             *
@@ -899,7 +872,7 @@ GDbSnapshot *g_db_snapshot_new_empty(const char *tmpdir, const char *hash, GList
 *                                                                             *
 ******************************************************************************/
 
-GDbSnapshot *g_db_snapshot_new_from_xml(const char *tmpdir, const char *hash, xmlDocPtr xdoc, xmlXPathContextPtr context)
+GDbSnapshot *g_db_snapshot_new_from_xml(const GCdbArchive *archive, xmlDocPtr xdoc, xmlXPathContextPtr context)
 {
     GDbSnapshot *result;                    /* Adresse à retourner         */
     xmlXPathObjectPtr xobject;              /* Cible d'une recherche       */
@@ -916,7 +889,7 @@ GDbSnapshot *g_db_snapshot_new_from_xml(const char *tmpdir, const char *hash, xm
     snapshot_node_t *node;                  /* Instantané nouveau constitué*/
     snapshot_id_t node_id;                  /* Identifiant de noeud courant*/
 
-    result = g_db_snapshot_new(tmpdir, hash);
+    result = g_db_snapshot_new(archive);
     if (result == NULL) goto exit;
 
     /* Chargement de l'ensemble des instantanés */
@@ -1042,7 +1015,8 @@ GDbSnapshot *g_db_snapshot_new_from_xml(const char *tmpdir, const char *hash, xm
 /******************************************************************************
 *                                                                             *
 *  Paramètres  : snap    = gestionnaire d'instantanés à constituer.           *
-*                archive = archive en cours de lecture.                       *
+*                ar      = archive en cours de lecture.                       *
+*                archive = archive associée à l'instantané.                   *
 *                                                                             *
 *  Description : Associe une base de données aux instantanés chargés.         *
 *                                                                             *
@@ -1052,7 +1026,7 @@ GDbSnapshot *g_db_snapshot_new_from_xml(const char *tmpdir, const char *hash, xm
 *                                                                             *
 ******************************************************************************/
 
-bool g_db_snapshot_fill(GDbSnapshot *snap, struct archive *archive)
+bool g_db_snapshot_fill(GDbSnapshot *snap, struct archive *ar, const GCdbArchive *archive)
 {
     bool result;                            /* Bilan à retourner           */
     struct archive_entry *entry;            /* Elément de l'archive        */
@@ -1066,9 +1040,9 @@ bool g_db_snapshot_fill(GDbSnapshot *snap, struct archive *archive)
 
     result = false;
 
-    for (ret = archive_read_next_header(archive, &entry);
+    for (ret = archive_read_next_header(ar, &entry);
          ret == ARCHIVE_OK;
-         ret = archive_read_next_header(archive, &entry))
+         ret = archive_read_next_header(ar, &entry))
     {
         path = archive_entry_pathname(entry);
 
@@ -1077,7 +1051,7 @@ bool g_db_snapshot_fill(GDbSnapshot *snap, struct archive *archive)
 
         if (strcmp(path, "current.db") == 0)
         {
-            if (!dump_archive_entry_into_file(archive, entry, snap->current_db))
+            if (!dump_archive_entry_into_file(ar, entry, snap->current_db))
                 break;
 
             continue;
@@ -1098,10 +1072,10 @@ bool g_db_snapshot_fill(GDbSnapshot *snap, struct archive *archive)
         if (node == NULL)
             break;
 
-        if (!setup_snapshot_node_db_path(node, snap->tmpdir, snap->hash))
+        if (!setup_snapshot_node_db_path(node, archive))
             break;
 
-        if (!dump_archive_entry_into_file(archive, entry, node->path))
+        if (!dump_archive_entry_into_file(ar, entry, node->path))
             break;
 
     }
@@ -1482,8 +1456,9 @@ DBError g_db_snapshot_restore(GDbSnapshot *snap, packed_buffer_t *pbuf, bool *re
 
 /******************************************************************************
 *                                                                             *
-*  Paramètres  : snap = gestionnaire d'instantanés à consulter.               *
-*                db   = base de données courante.                             *
+*  Paramètres  : snap    = gestionnaire d'instantanés à consulter.            *
+*                db      = base de données courante.                          *
+*                archive = archive associée à l'instantané.                   *
 *                                                                             *
 *  Description : Crée un nouvel instantanés dans l'arborescence.              *
 *                                                                             *
@@ -1493,7 +1468,7 @@ DBError g_db_snapshot_restore(GDbSnapshot *snap, packed_buffer_t *pbuf, bool *re
 *                                                                             *
 ******************************************************************************/
 
-DBError g_db_snapshot_create(GDbSnapshot *snap, sqlite3 *db)
+DBError g_db_snapshot_create(GDbSnapshot *snap, sqlite3 *db, const GCdbArchive *archive)
 {
     DBError result;                         /* Conclusion à retourner      */
     snapshot_node_t *new;                   /* Nouvel instantané           */
@@ -1503,7 +1478,7 @@ DBError g_db_snapshot_create(GDbSnapshot *snap, sqlite3 *db)
 
     new = create_snapshot_node(NULL, 0, NULL, NULL);
 
-    status = setup_snapshot_node_db_path(new, snap->tmpdir, snap->hash);
+    status = setup_snapshot_node_db_path(new, archive);
     if (!status)
     {
         result = DBE_SYS_ERROR;
diff --git a/src/analysis/db/snapshot.h b/src/analysis/db/snapshot.h
index 7f8a82a..59a2ba7 100644
--- a/src/analysis/db/snapshot.h
+++ b/src/analysis/db/snapshot.h
@@ -33,6 +33,7 @@
 #include <libxml/xpath.h>
 
 
+#include "cdb.h"
 #include "protocol.h"
 #include "misc/snapshot.h"
 
@@ -57,13 +58,13 @@ typedef struct _GDbSnapshotClass GDbSnapshotClass;
 GType g_db_snapshot_get_type(void);
 
 /* Prépare un gestionnaire d'instantanés de bases de données. */
-GDbSnapshot *g_db_snapshot_new_empty(const char *, const char *, GList *);
+GDbSnapshot *g_db_snapshot_new_empty(const GCdbArchive *, GList *);
 
 /* Charge un gestionnaire d'instantanés de bases de données. */
-GDbSnapshot *g_db_snapshot_new_from_xml(const char *, const char *, xmlDocPtr, xmlXPathContextPtr);
+GDbSnapshot *g_db_snapshot_new_from_xml(const GCdbArchive *, xmlDocPtr, xmlXPathContextPtr);
 
 /* Associe une base de données aux instantanés chargés. */
-bool g_db_snapshot_fill(GDbSnapshot *, struct archive *);
+bool g_db_snapshot_fill(GDbSnapshot *, struct archive *, const GCdbArchive *);
 
 /* Enregistre tous les éléments associés aux instantanés. */
 DBError g_db_snapshot_save(const GDbSnapshot *, xmlDocPtr, xmlXPathContextPtr, struct archive *);
@@ -87,7 +88,7 @@ DBError g_db_snapshot_set_desc(const GDbSnapshot *, packed_buffer_t *);
 DBError g_db_snapshot_restore(GDbSnapshot *, packed_buffer_t *, bool *);
 
 /* Crée un nouvel instantanés dans l'arborescence. */
-DBError g_db_snapshot_create(GDbSnapshot *, sqlite3 *);
+DBError g_db_snapshot_create(GDbSnapshot *, sqlite3 *, const GCdbArchive *);
 
 /* Supprime un instantané dans l'arborescence. */
 DBError g_db_snapshot_remove(GDbSnapshot *, packed_buffer_t *, bool *);
-- 
cgit v0.11.2-87-g4458