From 8d71f1b7ee8714004e7ccb0ed2f0a09e8b610ce8 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Sat, 12 May 2018 13:15:23 +0200 Subject: Created helpers for dealing with archives. --- src/analysis/db/cdb.c | 131 +++++++++-------------------------- src/common/Makefile.am | 1 + src/common/compression.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++ src/common/compression.h | 52 ++++++++++++++ 4 files changed, 259 insertions(+), 100 deletions(-) create mode 100644 src/common/compression.c create mode 100644 src/common/compression.h diff --git a/src/analysis/db/cdb.c b/src/analysis/db/cdb.c index 9479b4d..bcd3ed3 100644 --- a/src/analysis/db/cdb.c +++ b/src/analysis/db/cdb.c @@ -24,11 +24,8 @@ #include "cdb.h" -#include -#include #include #include -#include #include #include #include @@ -46,9 +43,9 @@ #include "collection.h" #include "protocol.h" +#include "../../common/compression.h" #include "../../common/cpp.h" #include "../../common/extstr.h" -#include "../../common/io.h" #include "../../common/pathname.h" #include "../../common/xml.h" #include "../../core/collections.h" @@ -56,11 +53,6 @@ -/* Fixe le tampon pour la lecture des fichiers à inclure */ -#define ARCHIVE_RBUF_SIZE 2048 - - - /* Informations relatives à un client */ typedef struct _cdb_client { @@ -413,8 +405,6 @@ static bool g_cdb_archive_read(GCdbArchive *archive) bool result; /* Conclusion à retourner */ struct archive *in; /* Archive à consulter */ int ret; /* Bilan d'un appel */ - int flags; /* Propriétés à extraire */ - struct archive *out; /* Extracteur générique */ struct archive_entry *entry; /* Elément de l'archive */ const char *path; /* Désignation d'un fichier */ @@ -427,54 +417,15 @@ static bool g_cdb_archive_read(GCdbArchive *archive) ret = archive_read_open_filename(in, archive->filename, 10240 /* ?! */); if (ret != ARCHIVE_OK) goto gcar_exit; - /* Propriétés à restaurer */ - flags = ARCHIVE_EXTRACT_TIME; - flags |= ARCHIVE_EXTRACT_PERM; - flags |= ARCHIVE_EXTRACT_ACL; - flags |= ARCHIVE_EXTRACT_FFLAGS; - - out = archive_write_disk_new(); - archive_write_disk_set_options(out, flags); - archive_write_disk_set_standard_lookup(out); - for (ret = archive_read_next_header(in, &entry); ret == ARCHIVE_OK; ret = archive_read_next_header(in, &entry)) { - bool dump_arch_data(struct archive_entry *ent, struct archive *input, struct archive *output) - { - const void *buff; /* Tampon de copie */ - size_t size; /* Quantité copiée */ - __LA_INT64_T offset; /* Position de lecture */ - - ret = archive_write_header(output, entry); - if (ret != ARCHIVE_OK) return false; - - for (ret = archive_read_data_block(input, &buff, &size, &offset); - ret == ARCHIVE_OK; - ret = archive_read_data_block(input, &buff, &size, &offset)) - { - ret = archive_write_data_block(output, buff, size, offset); - if (ret != ARCHIVE_OK) - return false; - } - - if (ret != ARCHIVE_EOF) - return false; - - ret = archive_write_finish_entry(output); - - return (ret == ARCHIVE_OK); - - } - path = archive_entry_pathname(entry); if (strcmp(path, "desc.xml") == 0) { - archive_entry_set_pathname(entry, archive->xml_desc); - - if (!dump_arch_data(entry, in, out)) + if (!dump_archive_entry_into_file(in, entry, archive->xml_desc)) goto gcar_exit; if (!open_xml_file(archive->xml_desc, &archive->xdoc, &archive->context)) @@ -483,9 +434,7 @@ static bool g_cdb_archive_read(GCdbArchive *archive) } else if (strcmp(path, "sql.db") == 0) { - archive_entry_set_pathname(entry, archive->sql_db); - - if (!dump_arch_data(entry, in, out)) + if (!dump_archive_entry_into_file(in, entry, archive->sql_db)) goto gcar_exit; ret = sqlite3_open(archive->sql_db, &archive->db); @@ -499,9 +448,6 @@ static bool g_cdb_archive_read(GCdbArchive *archive) archive_read_close(in); archive_read_free(in); - archive_write_close(out); - archive_write_free(out); - result = true; gcar_exit: @@ -528,6 +474,7 @@ DBError g_cdb_archive_write(const GCdbArchive *archive) DBError result; /* Conclusion à retourner */ struct archive *out; /* Archive à constituer */ int ret; /* Bilan d'un appel */ + CPError status; /* Bilan d'une compression */ result = DBE_ARCHIVE_ERROR; @@ -538,62 +485,46 @@ DBError g_cdb_archive_write(const GCdbArchive *archive) ret = archive_write_open_filename(out, archive->filename); if (ret != ARCHIVE_OK) goto gcaw_exit; - DBError add_file_to_archive(struct archive *out, const char *src, const char *path) - { - DBError status; /* Bilan à renvoyer */ - struct stat info; /* Informations d'origine */ - struct archive_entry *entry; /* Elément de l'archive */ - int fd; /* Flux ouvert en lecture */ - char buffer[ARCHIVE_RBUF_SIZE]; /* Tampon pour les transferts */ - ssize_t len; /* Quantité de données lues */ - - status = DBE_ARCHIVE_ERROR; + status = add_file_into_archive(out, archive->xml_desc, "desc.xml"); - ret = stat(src, &info); - if (ret != 0) return DBE_SYS_ERROR; + switch (status) + { + case CPE_NO_ERROR: + result = DBE_NONE; + break; - entry = archive_entry_new(); + case CPE_SYSTEM_ERROR: + result = DBE_SYS_ERROR; + break; - archive_entry_copy_stat(entry, &info); - archive_entry_set_pathname(entry, path); + case CPE_ARCHIVE_ERROR: + result = DBE_ARCHIVE_ERROR; + break; - ret = archive_write_header(out, entry); - if (ret != 0) goto afta_error; + } - fd = open(src, O_RDONLY); - if (fd == -1) - { - status = DBE_SYS_ERROR; - goto afta_error; - } + if (result == DBE_NONE) + { + status = add_file_into_archive(out, archive->sql_db, "sql.db"); - for (len = safe_read_partial(fd, buffer, ARCHIVE_RBUF_SIZE); - len > 0; - len = safe_read_partial(fd, buffer, ARCHIVE_RBUF_SIZE)) + switch (status) { - if (archive_write_data(out, buffer, len) != len) - goto afta_error; - } - - close(fd); - - archive_entry_free(entry); - - return DBE_NONE; + case CPE_NO_ERROR: + result = DBE_NONE; + break; - afta_error: + case CPE_SYSTEM_ERROR: + result = DBE_SYS_ERROR; + break; - archive_entry_free(entry); + case CPE_ARCHIVE_ERROR: + result = DBE_ARCHIVE_ERROR; + break; - return status; + } } - result = add_file_to_archive(out, archive->xml_desc, "desc.xml"); - - if (result == DBE_NONE) - result = add_file_to_archive(out, archive->sql_db, "sql.db"); - gcaw_exit: archive_write_free(out); diff --git a/src/common/Makefile.am b/src/common/Makefile.am index b5b008c..7a13aa8 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -6,6 +6,7 @@ libcommon_la_SOURCES = \ asm.h asm.c \ bconst.h \ bits.h bits.c \ + compression.h compression.c \ cpp.h \ dllist.h dllist.c \ endianness.h endianness.c \ diff --git a/src/common/compression.c b/src/common/compression.c new file mode 100644 index 0000000..d443924 --- /dev/null +++ b/src/common/compression.c @@ -0,0 +1,175 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * compression.c - facilités de manipulation des archives + * + * Copyright (C) 2018 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 . + */ + + +#include "compression.h" + + +#include +#include + + +#include "io.h" + + + +/* Fixe le tampon pour la lecture des fichiers à inclure */ +#define ARCHIVE_RBUF_SIZE 2048 + + + +/****************************************************************************** +* * +* Paramètres : output = archive dont le contenu est à composer. * +* filename = chemin d'accès au fichier d'entrée. * +* path = chemin d'accès dans l'archive. * +* * +* Description : Ajoute un élement à une archive. * +* * +* Retour : Code de retour pour l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +CPError add_file_into_archive(struct archive *output, const char *filename, const char *path) +{ + CPError result; /* Code de retour à renvoyer */ + struct stat info; /* Informations d'origine */ + int ret; /* Bilan d'un appel */ + struct archive_entry *entry; /* Elément de l'archive */ + int fd; /* Flux ouvert en lecture */ + char buffer[ARCHIVE_RBUF_SIZE]; /* Tampon pour les transferts */ + ssize_t len; /* Quantité de données lues */ + + result = CPE_ARCHIVE_ERROR; + + ret = stat(filename, &info); + if (ret != 0) + { + perror("stat"); + result = CPE_SYSTEM_ERROR; + goto afia_exit; + } + + entry = archive_entry_new(); + + archive_entry_copy_stat(entry, &info); + archive_entry_set_pathname(entry, path); + + ret = archive_write_header(output, entry); + if (ret != 0) goto afia_exit; + + fd = open(filename, O_RDONLY); + if (fd == -1) + { + perror("open"); + result = CPE_SYSTEM_ERROR; + goto afia_exit; + } + + for (len = safe_read_partial(fd, buffer, ARCHIVE_RBUF_SIZE); + len > 0; + len = safe_read_partial(fd, buffer, ARCHIVE_RBUF_SIZE)) + { + if (archive_write_data(output, buffer, len) != len) + goto afia_exit; + } + + close(fd); + + archive_entry_free(entry); + + return CPE_NO_ERROR; + + afia_exit: + + archive_entry_free(entry); + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : intput = archive dont le contenu est à extraire. * +* entry = entrée de l'archive à extraire. * +* filename = chemin d'accès au fichier de sortie. * +* * +* Description : Extrait un élement d'une archive. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool dump_archive_entry_into_file(struct archive *input, struct archive_entry *entry, const char *filename) +{ + bool result; /* Conclusion à retourner */ + int flags; /* Propriétés à extraire */ + struct archive *output; /* Extracteur générique */ + int ret; /* Bilan d'un appel */ + const void *buff; /* Tampon de copie */ + size_t size; /* Quantité copiée */ + __LA_INT64_T offset; /* Position de lecture */ + + result = false; + + archive_entry_set_pathname(entry, filename); + + /* Propriétés à restaurer */ + flags = ARCHIVE_EXTRACT_TIME; + flags |= ARCHIVE_EXTRACT_PERM; + flags |= ARCHIVE_EXTRACT_ACL; + flags |= ARCHIVE_EXTRACT_FFLAGS; + + output = archive_write_disk_new(); + archive_write_disk_set_options(output, flags); + archive_write_disk_set_standard_lookup(output); + + ret = archive_write_header(output, entry); + if (ret != ARCHIVE_OK) goto daeif_exit; + + for (ret = archive_read_data_block(input, &buff, &size, &offset); + ret == ARCHIVE_OK; + ret = archive_read_data_block(input, &buff, &size, &offset)) + { + ret = archive_write_data_block(output, buff, size, offset); + } + + if (ret != ARCHIVE_EOF) + goto daeif_exit; + + ret = archive_write_finish_entry(output); + + result = (ret == ARCHIVE_OK); + + daeif_exit: + + archive_write_close(output); + archive_write_free(output); + + return result; + +} diff --git a/src/common/compression.h b/src/common/compression.h new file mode 100644 index 0000000..632147a --- /dev/null +++ b/src/common/compression.h @@ -0,0 +1,52 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * compression.h - prototypes pour les facilités de manipulation des archives + * + * Copyright (C) 2018 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 . + */ + + +#ifndef _COMMON_COMPRESSION_H +#define _COMMON_COMPRESSION_H + + +#include +#include +#include + + + +/* Codes de retour pour la compression */ +typedef enum _CPError +{ + CPE_NO_ERROR, /* Aucun souci particulier */ + CPE_SYSTEM_ERROR, /* Le soucis vient de l'archive*/ + CPE_ARCHIVE_ERROR /* Le soucis vient du système */ + +} CPError; + + +/* Ajoute un élement à une archive. */ +CPError add_file_into_archive(struct archive *, const char *, const char *); + +/* Extrait un élement d'une archive. */ +bool dump_archive_entry_into_file(struct archive *, struct archive_entry *, const char *); + + + +#endif /* _COMMON_COMPRESSION_H */ -- cgit v0.11.2-87-g4458