From b03d779e0b9623d307f9e2a56a0b152365497ba9 Mon Sep 17 00:00:00 2001 From: Pierre Date: Wed, 30 Sep 2026 09:40:01 +0200 Subject: [PATCH] =?UTF-8?q?Suppression=20de=20No=5Fpaquet=20:=20marquage?= =?UTF-8?q?=20par=20ligne=20(Archive)=20remplace=20ce=20m=C3=A9canisme=20d?= =?UTF-8?q?ans=20sauvegarde=5Fbdd(),=20nom=20de=20fichier=20avec=20emprein?= =?UTF-8?q?te=20SHA-256,=20en-t=C3=AAte=20MMSI,=20mot=20de=20passe=20de=20?= =?UTF-8?q?chiffrement=20d=C3=A9di=C3=A9=20(cf=20synth=C3=A8se=20=C2=A732)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sources/bdd_admin.c | 365 +++++++++++++++++++++++++++++++++++++++- sources/bdd_fonctions.c | 8 +- sources/bdd_init.c | 1 - sources/localisation.h | 2 + sources/main.h | 1 - sources/systeme.c | 10 +- 6 files changed, 377 insertions(+), 10 deletions(-) diff --git a/sources/bdd_admin.c b/sources/bdd_admin.c index fb0a3b2..c20f63d 100644 --- a/sources/bdd_admin.c +++ b/sources/bdd_admin.c @@ -18,7 +18,7 @@ int8_t archivage_bdd(char * chaine_date_fin, uint8_t type); // Variables globales : - +/* //================================================================================================================================================================== // Fonction : Cette fonction génère un fichier de sauvegarde de la base de données. // Le fichier est stocké dans le répertoire d'upload pour pouvoir être remonté au serveur Koriolan via FTP ensuite (cette remontée ne fait pas partie de la présente fonction) @@ -321,6 +321,369 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; affichage_debug(__FILE__, __LINE__, "Fin de sauvegarde de la BDD", TYPE_MESSAGE_DEBUG_PAR_DEFAUT); return(0); } +*/ + +//================================================================================================================================================================== +// Fonction : Cette fonction génère un fichier de sauvegarde de la base de données. +// Le fichier est stocké dans le répertoire d'upload pour pouvoir être remonté au serveur ship2net (récupéré via l'API shipheart_api, cf synthèse §32). +// La base de données est sauvegardée en totalité (tous les enregistrements de toutes les tables) SAUF : +// - les tables TB_Mesures_xxx : seuls les enregistrements dont le champ Archive vaut 0 sont remontés. +// - la table TB_Historique : seuls les enregistrements dont le champ Archive vaut 0 sont remontés. +// Le champ Archive de ces tables est mis à 1 une fois l'archive validée (remplace l'ancien mécanisme de No_paquet, +// source de risques en cas de réinitialisation usine ou de restauration d'une sauvegarde ancienne - cf synthèse §32.4). +// Le nom du fichier intègre désormais une empreinte (SHA-256 tronquée à 16 caractères) du fichier chiffré final, +// calculée une fois celui-ci produit et vérifié : elle sert à la fois de contrôle d'intégrité et d'identifiant +// unique côté serveur (il n'y a donc plus de notion de No_paquet dans le nom). +// Reçoit : Rien +// Renvoit : 0 si pas d'erreur. Valeur de retour du premier appel 'system()' qui est différent de 0. +//================================================================================================================================================================== +int32_t sauvegarde_bdd(void) +{ +int32_t retour_commande; +char str_date[MAX_LONGUEUR_DATE_COURANTE]; +char nom_base[75]; // _, sans extension ni empreinte +char nom_fichier_sauvegarde[MAX_LONGUEUR_NOM_FICHIER_SAUVEGARDE_BDD]; +char nom_fichier_final[MAX_LONGUEUR_NOM_FICHIER_SAUVEGARDE_BDD]; // Nom définitif, après renommage avec l'empreinte +char chemin_temp_empreinte[MAX_LONGUEUR_NOM_FICHIER_SAUVEGARDE_BDD]; +char empreinte[17]; // 16 caractères hexadécimaux + '\0' +char no_mmsi[16]; // "000000000" par défaut (9 chiffres) - cf TB_Configuration +FILE * ptr_fichier_sauvegarde; +FILE * ptr_fichier_empreinte; +char requete[MAX_LONGUEUR_REQUETE_MYSQL]; +char commande[MAX_TAILLE_COMMANDE_SHELL]; +char options[MAX_LONGUEUR_OPTION_COMMANDE_SAUVEGARDE_BDD]; +char filtre_table[MAX_LONGUEUR_OPTION_COMMANDE_SAUVEGARDE_BDD]; +char param[MAX_LONGUEUR_OPTION_COMMANDE_SAUVEGARDE_BDD]; +struct { + char nom[MAX_LONGUEUR_NOM_TABLE]; // Nom de la table (par exemple, TB_Mesures_capteurs') +} tables_fragmentees[MAX_NOMBRE_TABLES_FRAGMENTEES]; +uint8_t nb_tables_fragmentees; +MYSQL_RES *result = NULL; +MYSQL_ROW row = NULL; +uint16_t i; +char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; + + + sprintf(tmp, "Début de sauvegarde de la BDD (marquage par ligne, remplace No_paquet - cf synthèse §32.4)"); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT); + + // SDIR # 202 (début) : + // Vérification qu'une phase d'archivage n'est pas en cours (si c'est le cas, on va décaler la sauvagarde pour éviter de surcharger inutilement le système) : + if (get_pid_numbers_from_name(NOM_FICHIER_ARCHIVAGE, "") > 0) // Il y a au moins 1 processus d'archivage en cours... + { + systeme.compteur_sauvegarde_bdd = SYSTEME_TEMPO_REPORT_SAUVEGARDE; // Dans ce cas, on relance une tempo courte (5s typique) avant de refaire une tentative. + + sprintf(tmp, "Un processus [%s] a été détecté en cours d'exécution. La sauvegarde est temporisée pour %i secondes", NOM_FICHIER_ARCHIVAGE, systeme.compteur_sauvegarde_bdd); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + + return (-1); + } + // SDIR # 202 (fin) + + + + retour_commande = 0; + + // Calcul de la date et de l'heure, au bon format : + date_courante(str_date, DATE_COURANTE_SANS_MS, FORMAT_DATE_COURANTE_FICHIER); + + // NOUVEAU : lecture du MMSI courant (TB_Configuration.No_mmsi), transmis dans l'en-tête de l'archive (cf synthèse §32.3) : + sprintf(requete, "SELECT Valeur FROM TB_Configuration WHERE Nom='No_mmsi'"); + mysql_query(bdd.pointeur, requete); + result = mysql_store_result(bdd.pointeur); + if ((result != NULL) && ((row = mysql_fetch_row(result)) != NULL)) strcpy(no_mmsi, row[0]); + else strcpy(no_mmsi, "000000000"); // Valeur par défaut si jamais introuvable (ne devrait normalement pas arriver) + if (result != NULL) mysql_free_result(result); + + // Nom de base du fichier - SANS empreinte (inconnue à ce stade, calculée plus bas) NI No_paquet (abandonné) : + sprintf(nom_base, "%02X%02X%02X%02X%02X%02X_%s", + systeme.modules_physiques[0].adresse_mac[0], systeme.modules_physiques[0].adresse_mac[1], systeme.modules_physiques[0].adresse_mac[2], + systeme.modules_physiques[0].adresse_mac[3], systeme.modules_physiques[0].adresse_mac[4], systeme.modules_physiques[0].adresse_mac[5], + str_date); + sprintf(nom_fichier_sauvegarde, "%s/%s.sql", REPERTOIRE_SERVER_UPLOAD, nom_base); + + // Options de la commande de sauvegarde (utilisée sur la commande 'mysqldump' : + sprintf(options, "--single-transaction --no-create-info --compact --complete-insert"); + + + do // Fake loop... + { + //------------------------------------------------------------------------------------------- + // Remplissage de l'entête du fichier de sauvegarde (SDIR #292) : + //------------------------------------------------------------------------------------------- + ptr_fichier_sauvegarde = fopen(nom_fichier_sauvegarde, "w+"); // Ouverture du flux en lecture/écriture. Si le fichier existe, il sera alors écrasé et la position courante est fixée au début du fichier. Sinon le fichier sera créé. + if (ptr_fichier_sauvegarde == NULL) + { + printf("Ouverture du fichier de sauvegarde [ %s ] impossible. La sauvegarde est arrêtée !\n", nom_fichier_sauvegarde); + retour_commande = -1; + break; + } + + // Attention : le format '# [nom_de_champ=valeur_du_champ]' est utilisé par le traitement côté serveur... + // Il est donc fortement conseillé de ne PAS modifier le format de ces trames d'entête !!! + fprintf(ptr_fichier_sauvegarde, + "# [Adresse_mac=%02X:%02X:%02X:%02X:%02X:%02X]\n", + systeme.modules_physiques[0].adresse_mac[0], systeme.modules_physiques[0].adresse_mac[1], systeme.modules_physiques[0].adresse_mac[2], + systeme.modules_physiques[0].adresse_mac[3], systeme.modules_physiques[0].adresse_mac[4], systeme.modules_physiques[0].adresse_mac[5]); + fprintf(ptr_fichier_sauvegarde, "# [Nom_du_bateau=%s]\n", systeme.nom_bateau); + fprintf(ptr_fichier_sauvegarde, "# [Date_fichier=%s]\n", str_date); + fprintf(ptr_fichier_sauvegarde, "# [Version_soft_no_package=%s]\n", systeme.package_no_version); + fprintf(ptr_fichier_sauvegarde, "# [No_mmsi=%s]\n", no_mmsi); // NOUVEAU (cf synthèse §32.3/32.4) + + fclose(ptr_fichier_sauvegarde); + + // Fin de SDIR #292 + + + //------------------------------------------------------------------------------------------- + // Recherche des tables fragmentées : TB_Mesures* et TB_Historique + //------------------------------------------------------------------------------------------- + nb_tables_fragmentees = 0; + + // Tables de mesures : + sprintf(requete, "SHOW TABLES FROM shipheart LIKE 'TB_Mesures%%'"); + mysql_query(bdd.pointeur, requete); + result = mysql_store_result(bdd.pointeur); + while((row = mysql_fetch_row(result))) + { + strcpy(tables_fragmentees[nb_tables_fragmentees ++].nom, row[0]); + } + mysql_free_result(result); + + // Table historique : + strcpy(tables_fragmentees[nb_tables_fragmentees ++].nom, "TB_Historique"); + + // Vérification du nombre de tables max : + if (nb_tables_fragmentees > MAX_NOMBRE_TABLES_FRAGMENTEES) + { + sprintf(tmp, "Le nombre de tables fragmentées (qui sont sauvegardées par fragment) est supérieur au nombre maxi (%i tables trouvées pour maxi = %i). La sauvegarde de la BDD est arrêté.", nb_tables_fragmentees, MAX_NOMBRE_TABLES_FRAGMENTEES); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + retour_commande = -1; + break; + } + + //------------------------------------------------------------------------------------------- + // Sauvegarde de toutes les tables, sauf TB_Mesures* et TB_Historique : + //------------------------------------------------------------------------------------------- + + // Début de la commande de dump: + sprintf(commande, "mysqldump %s -u %s --password=%s %s ", options, BDD_USER, BDD_PASSWORD, BDD_DATABASE); + + // Suppression des tables fragmentées du dump : + for (i = 0; i < nb_tables_fragmentees; i ++) + { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wformat-overflow" + sprintf(param, "--ignore-table=%s.%s ", BDD_DATABASE, tables_fragmentees[i].nom); // Warning connu mais non justifié : tables_fragmentees[].nom : 50 car et param : 300 car + #pragma GCC diagnostic pop + + strcat(commande, param); + } + + // Fin de la commande : + sprintf(param, ">> %s ", nom_fichier_sauvegarde); + strcat(commande, param); + + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La commande de sauvegarde de toutes les tables non fragmentées [%s] a échoué avec le code %i", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + + //--------------------------------------------------------------------- + // Sauvegarde des derniers enregistrements des tables fragmentées : + // CHANGEMENT : le filtre passe de 'No_paquet=%i' à 'Archive=0' - le marquage effectif (Archive=1) n'a lieu que plus bas, une fois + // l'archive entièrement validée (cf synthèse §32.4). Tant que ce marquage n'a pas eu lieu, ces mêmes lignes seront reprises par la + // prochaine tentative en cas d'échec à n'importe quelle étape suivante. + //--------------------------------------------------------------------- + for (i = 0; i < nb_tables_fragmentees; i ++) + { + // Suppression des 'Type>0' pour TB_Mesures_circuits : + if (strstr(tables_fragmentees[i].nom, "TB_Mesures_circuits") != NULL) strcpy(filtre_table, " AND Type=0"); + else strcpy(filtre_table, ""); + sprintf(commande, "mysqldump %s -u %s --password=%s %s %s --where=\"Archive=0 %s \" >> %s", options, BDD_USER, BDD_PASSWORD, BDD_DATABASE, tables_fragmentees[i].nom, filtre_table, nom_fichier_sauvegarde); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La commande de sauvegarde de la table fragmentée %s [%s] a échoué avec le code %i", tables_fragmentees[i].nom, commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; // Sortie de la boucle FOR + } + } + if (retour_commande != 0) break; + + //--------------------------------------------------------------------- + // Compression du fichier de sauvegarde : + //--------------------------------------------------------------------- + // SDIR #170 : ajout du paramètre '-k' dans la commande de compresion afin de conserver le fichier SQL initial (sinon, il n'est pas conservé par GZIP) + sprintf(commande, "gzip %s -k -S .%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La commande de compression du fichier de sauvegarde [%s] a échoué avec le code %i", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + //--------------------------------------------------------------------- + // Encryption du fichier de sauvegarde : + // CHANGEMENT : mot de passe dédié (CLE_CHIFFREMENT_ARCHIVE), distinct + // de BDD_PASSWORD - à définir dans localisation.h (cf synthèse §32.4). + //--------------------------------------------------------------------- + sprintf(commande, "openssl enc -aes-256-cbc -pbkdf2 -iter 10000 -md sha256 -in %s.%s -out %s.%s.%s -pass pass:%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, SUFFIXE_NOM_FICHIER_ENCRYPTE_SAUVEGARDE_BDD, CLE_CHIFFREMENT_ARCHIVE); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La commande d'encryption du fichier de sauvegarde [%s] a échoué avec le code %i", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + //--------------------------------------------------------------------- + // Décryptage du fichier final (vérification - même mot de passe dédié) : + //--------------------------------------------------------------------- + sprintf(commande, "openssl enc -aes-256-cbc -pbkdf2 -iter 10000 -md sha256 -d -in %s.%s.%s -out %s/%s.sql.%s -pass pass:%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, SUFFIXE_NOM_FICHIER_ENCRYPTE_SAUVEGARDE_BDD, REPERTOIRE_TMP_BDD, NOM_FICHIER_CHECK_SAUVEGARDE, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, CLE_CHIFFREMENT_ARCHIVE); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La commande de décrytage temporaire du fichier de sauvegarde [%s] a échoué avec le code %i", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + //--------------------------------------------------------------------- + // Décompression du fichier temporaire : + //--------------------------------------------------------------------- + sprintf(commande, "gzip -d -f %s/%s.sql.%s", REPERTOIRE_TMP_BDD, NOM_FICHIER_CHECK_SAUVEGARDE, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La commande de décompression temporaire [%s] a échoué avec le code %i", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + //--------------------------------------------------------------------- + // Comparaison du fichier temporaire avec le fichier inital : + //--------------------------------------------------------------------- + sprintf(commande, "diff -q %s %s/%s.sql", nom_fichier_sauvegarde, REPERTOIRE_TMP_BDD, NOM_FICHIER_CHECK_SAUVEGARDE); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "La comparaison du fichier temporaire avec le fichier inital [%s] indique deux fichiers différents [%i]", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + //--------------------------------------------------------------------- + // NOUVEAU : calcul de l'empreinte (SHA-256 tronquée à 16 caractères) + // du fichier chiffré final, et renommage pour l'y intégrer. Ne se + // fait qu'à ce stade : la vérification ci-dessus (diff) vient de + // confirmer que ce fichier est intègre, donc l'empreinte qu'on y + // appose est fiable (cf synthèse §32.4). + //--------------------------------------------------------------------- + sprintf(chemin_temp_empreinte, "%s/empreinte_archive.tmp", REPERTOIRE_TMP_BDD); + sprintf(commande, "sha256sum %s.%s.%s | cut -c1-16 > %s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, SUFFIXE_NOM_FICHIER_ENCRYPTE_SAUVEGARDE_BDD, chemin_temp_empreinte); + retour_commande = commande_shell(commande); + if (retour_commande != 0) + { + sprintf(tmp, "Le calcul de l'empreinte du fichier de sauvegarde [%s] a échoué avec le code %i", commande, retour_commande); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + break; + } + + ptr_fichier_empreinte = fopen(chemin_temp_empreinte, "r"); + if ((ptr_fichier_empreinte == NULL) || (fgets(empreinte, sizeof(empreinte), ptr_fichier_empreinte) == NULL)) + { + sprintf(tmp, "La lecture de l'empreinte calculée [%s] a échoué.", chemin_temp_empreinte); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + if (ptr_fichier_empreinte != NULL) fclose(ptr_fichier_empreinte); + retour_commande = -1; + break; + } + fclose(ptr_fichier_empreinte); + remove(chemin_temp_empreinte); + empreinte[16] = '\0'; // Sécurité : ne garder que les 16 premiers caractères, même si un caractère de fin de ligne traînait + + sprintf(nom_fichier_final, "%s/%s_%s.sql.%s.%s", REPERTOIRE_SERVER_UPLOAD, nom_base, empreinte, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, SUFFIXE_NOM_FICHIER_ENCRYPTE_SAUVEGARDE_BDD); + sprintf(commande, "%s.%s.%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, SUFFIXE_NOM_FICHIER_ENCRYPTE_SAUVEGARDE_BDD); + if (rename(commande, nom_fichier_final) != 0) + { + sprintf(tmp, "Le renommage du fichier de sauvegarde [%s] vers [%s] a échoué.", commande, nom_fichier_final); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + retour_commande = -1; + break; + } + + //--------------------------------------------------------------------- + // NOUVEAU : marquage des lignes archivées (remplace l'incrémentation + // de No_paquet). Même filtre que celui utilisé pour le dump (donc + // 'AND Type=0' repris pour TB_Mesures_circuits), pour ne marquer que + // ce qui vient réellement d'être archivé (cf synthèse §32.4) : + //--------------------------------------------------------------------- + for (i = 0; i < nb_tables_fragmentees; i ++) + { + if (strstr(tables_fragmentees[i].nom, "TB_Mesures_circuits") != NULL) strcpy(filtre_table, " AND Type=0"); + else strcpy(filtre_table, ""); + sprintf(requete, "UPDATE %s SET Archive=1 WHERE Archive=0 %s", tables_fragmentees[i].nom, filtre_table); + if (mysql_query(bdd.pointeur, requete) != 0) + { + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wformat-overflow" + sprintf(tmp, "Le marquage des lignes archivées de la table %s [%s] a échoué : %s", tables_fragmentees[i].nom, requete, mysql_error(bdd.pointeur)); + #pragma GCC diagnostic pop + + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + retour_commande = -1; + break; // Sortie de la boucle FOR + } + } + if (retour_commande != 0) break; + + } while(0); + + + //--------------------------------------------------------------------- + // Vérification que la sauvegarde s'est bien passée et retour : + //--------------------------------------------------------------------- + if (retour_commande != 0) // Cas où au moins l'une des opérations de sauvegarde ne s'est pas bien passée + { + // Enregistrement dans l'historique : + enregistrement_historique(TYPE_SOURCE_HISTORIQUE_SYSTEME, SYSTEME_ERREUR_SAUVEGARDE_BDD, 0, 0, tmp); + + // Suppression de tous les fichiers possibles, quelle que soit l'étape où l'échec a eu lieu (y compris après renommage) : + remove(nom_fichier_sauvegarde); + sprintf(commande, "%s.%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD); + remove(commande); + sprintf(commande, "%s.%s.%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD, SUFFIXE_NOM_FICHIER_ENCRYPTE_SAUVEGARDE_BDD); + remove(commande); + remove(nom_fichier_final); // Au cas où l'échec ait eu lieu APRÈS le renommage (lors du marquage des lignes, par exemple) + + sprintf(tmp, "La sauvegarde de la BDD est abandonnée. Les fichiers créés ont été supprimés."); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + // NB : contrairement à l'ancien mécanisme (No_paquet non incrémenté en cas d'échec), le marquage par ligne + // (Archive=1) n'est fait qu'en tout dernier lieu, une fois le fichier final confirmé intègre et renommé - + // un échec à n'importe quelle étape antérieure laisse donc naturellement les lignes concernées à Archive=0, + // qui seront reprises par la prochaine tentative sans aucune action supplémentaire nécessaire. + + return(retour_commande); + } + else // Cas normal, sans erreur : + { + // Supression du fichier SQL (qui a été volontairement conservé via le paramètre '-k' de GZIP)... + // ... et du fichier compressé (openssl ne peut pas "écraser" la source si elle est dans le même répertoire ; on le fait donc manuellement)... + // ... seul le fichier final (chiffré et renommé avec son empreinte) est conservé : + remove(nom_fichier_sauvegarde); + sprintf(commande, "%s.%s", nom_fichier_sauvegarde, SUFFIXE_NOM_FICHIER_COMPRESSE_SAUVEGARDE_BDD); + remove(commande); + } + + affichage_debug(__FILE__, __LINE__, "Fin de sauvegarde de la BDD", TYPE_MESSAGE_DEBUG_PAR_DEFAUT); + return(0); +} diff --git a/sources/bdd_fonctions.c b/sources/bdd_fonctions.c index dd76533..fe65f1a 100644 --- a/sources/bdd_fonctions.c +++ b/sources/bdd_fonctions.c @@ -972,7 +972,7 @@ char requete[MAX_LONGUEUR_REQUETE_MYSQL]; // Enregistrement si cela est autorisé : if (flag_enregistrement) { - sprintf(requete, "INSERT INTO TB_Historique (Type_source, ID_Source, Type, Valeur, Complement, No_paquet) VALUES (%i, %i, %i, %.4f, '%s', %i)", type_source, id_source, type, valeur, complement, systeme.no_paquet); + sprintf(requete, "INSERT INTO TB_Historique (Type_source, ID_Source, Type, Valeur, Complement) VALUES (%i, %i, %i, %.4f, '%s')", type_source, id_source, type, valeur, complement); // printf("Requete d'enregistrement dans l'historique = [ %s; ]\n", requete); mysql_query(bdd.pointeur, requete); } @@ -1295,7 +1295,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; #endif variables->last_mesure = FLT_MAX; // Initialisation à la valeur maximale d'un float pour être sûr que le prochain appel générera un enregistrement... - sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date, No_paquet) VALUES ('%i', '%i', NULL, '%s', '%i')", nom_table, cle_primaire, variable->cle_primaire, str_date, systeme.no_paquet); + sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date) VALUES ('%i', '%i', NULL, '%s')", nom_table, cle_primaire, variable->cle_primaire, str_date); // printf("Requete d'enregistement mesure = %s\n", requete); mysql_query(bdd.pointeur, requete); // Enregistrement dans la BDD @@ -1317,7 +1317,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; #endif variables->last_mesure = valeur; // Mémorisation de la dernière valeur enregistrée dans mesures pour usage ultérieur. - sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date, No_paquet) VALUES ('%i', '%i', '%f', '%s', '%i')", nom_table, cle_primaire, variable->cle_primaire, valeur, str_date, systeme.no_paquet); + sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date) VALUES ('%i', '%i', '%f', '%s')", nom_table, cle_primaire, variable->cle_primaire, valeur, str_date); // printf("Requete d'enregistement mesure = %s\n", requete); mysql_query(bdd.pointeur, requete); // Enregistrement dans la BDD } @@ -1348,7 +1348,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; #endif variables->last_mesure = valeur; // Mémorisation de la dernière valeur enregistrée dans mesures pour usage ultérieur. - sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date, No_paquet) VALUES ('%i', '%i', '%f', '%s', '%i')", nom_table, cle_primaire, variable->cle_primaire, valeur, str_date_ponctuelle, systeme.no_paquet); + sprintf(requete, "INSERT INTO %s (ID, ID_Variable, Valeur, Date) VALUES ('%i', '%i', '%f', '%s')", nom_table, cle_primaire, variable->cle_primaire, valeur, str_date_ponctuelle); // printf("Requete d'enregistement mesure = %s\n", requete); mysql_query(bdd.pointeur, requete); // Enregistrement dans la BDD } diff --git a/sources/bdd_init.c b/sources/bdd_init.c index 14db43c..a464943 100644 --- a/sources/bdd_init.c +++ b/sources/bdd_init.c @@ -151,7 +151,6 @@ affichage_debug(__FILE__, __LINE__, "------------------BDD_INIT", TYPE_MESSAGE_D if (strcmp(row[0], "Etat_modem") == 0) modem.etat = atoi(row[1]); else if (strcmp(row[0], "Presence_jack") == 0) audio.etat_presence_jack = atoi(row[1]); else if (strcmp(row[0], "Presence_sim") == 0) modem.etat_presence_sim = atoi(row[1]); - else if (strcmp(row[0], "No_paquet") == 0) systeme.no_paquet = atoi(row[1]); // Les adresses IP sont systématiquement réinitialisées à ADRESSE_IP_INCONNUE dans l'init de 'systeme.c' : // else if (strcmp(row[0], "Adresse_ip_ethernet") == 0) strcpy(systeme.adresse_ip_ethernet, row[1]); // else if (strcmp(row[0], "Adresse_ip_wifi_sta") == 0) strcpy(systeme.adresse_ip_wifi_sta, row[1]); diff --git a/sources/localisation.h b/sources/localisation.h index a110a8b..e9663d4 100644 --- a/sources/localisation.h +++ b/sources/localisation.h @@ -8,6 +8,7 @@ #define BDD_USER "koriolan" #define BDD_PASSWORD "Mp7Hgf12bV9zm" #define BDD_DATABASE "shipheart" +#define CLE_CHIFFREMENT_ARCHIVE "Xd5Ps69nVF2WsQA7" // Répertoires : @@ -17,6 +18,7 @@ #define REPERTOIRE_CONFIG "/home/koriolan/shipheart/config" // Pas de '/' de fin... #define REPERTOIRE_CONFIG_IMAGES_ACCUEIL "/home/koriolan/shipheart/config/images_accueil" // Pas de '/' de fin... #define REPERTOIRE_CONFIG_IMAGES_SILHOUETTE "/home/koriolan/shipheart/config/images_silhouette" // Pas de '/' de fin... +#define REPERTOIRE_CONFIG_IMAGES_RAPPORTS "/home/koriolan/shipheart/config/images_rapports" // Pas de '/' de fin... #define REPERTOIRE_CONFIG_RAPPORTS "/home/koriolan/shipheart/config/rapports" // Pas de '/' de fin... #define REPERTOIRE_CONFIG_SAUVEGARDES "/home/koriolan/shipheart/config/sauvegardes" // Pas de '/' de fin... #define REPERTOIRE_CONFIG_SONS "/home/koriolan/shipheart/config/sons" // Pas de '/' de fin... diff --git a/sources/main.h b/sources/main.h index 4bb8dd9..b4198cb 100644 --- a/sources/main.h +++ b/sources/main.h @@ -1227,7 +1227,6 @@ struct Struct_systeme bool flag_new_download; // Positionné à TRUE (par 'modem.c') quand de nouveaux fichiers ont été downloadés du serveur. Permet à 'systeme.c' de lancer l'analyse de ces fichiers. uint16_t compteur_sauvegarde_bdd; // En secondes uint16_t compteur_check_new_download; // En secondes - uint32_t no_paquet; // N° du paquet en cours de constitution mais pas encore envoyé (issu de TB_Système au démarrage puis mis à jour à chaque envoi de paquet) char cm3p_soft_version[MAX_TAILLE_VERSION_SOFT]; // Contient la version de soft de l'application char package_version[MAX_TAILLE_VERSION_SOFT]; // Contient la version de package sous la forme 'AAMMJJ_HHMMSS' char package_no_version[MAX_TAILLE_VERSION_SOFT]; // Contient le numéro de la version du package. Par exemple : "1.0.7" diff --git a/sources/systeme.c b/sources/systeme.c index db5f17a..f883316 100644 --- a/sources/systeme.c +++ b/sources/systeme.c @@ -102,6 +102,10 @@ char commande[MAX_TAILLE_COMMANDE_SHELL]; repertoire = opendir(REPERTOIRE_CONFIG_IMAGES_SILHOUETTE); // Tentative d'ouverture du répertoire... if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_IMAGES_SILHOUETTE, 0777); // ...et création s'il n'existe pas else closedir(repertoire); + + repertoire = opendir(REPERTOIRE_CONFIG_IMAGES_RAPPORTS); // Tentative d'ouverture du répertoire... + if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_IMAGES_RAPPORTS, 0777); // ...et création s'il n'existe pas + else closedir(repertoire); repertoire = opendir(REPERTOIRE_CONFIG_RAPPORTS); // Tentative d'ouverture du répertoire... if (repertoire == NULL) mkdir(REPERTOIRE_CONFIG_RAPPORTS, 0777); // ...et création s'il n'existe pas @@ -387,8 +391,8 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //------------------------------------ // Sauvegarde de la base de données : affichage_debug(__FILE__, __LINE__, "Lancement sauvegarde BDD\t\t: OK", TYPE_MESSAGE_DEBUG_OK); -//ret = sauvegarde_bdd(); -ret=0; + ret = sauvegarde_bdd(); + if (ret != 0) { sprintf(tmp, "\tSauvegarde de la base de données : NOK (retour = %i)", ret); @@ -436,7 +440,7 @@ ret=0; if (systeme.compteur_sauvegarde_bdd == 0) { systeme.compteur_sauvegarde_bdd = systeme.periode_sauvegarde_bdd; // Provenance = 'Periode_sauvegarde_bdd' de TB_Configuration -// sauvegarde_bdd(); + sauvegarde_bdd(); } //======================================================