/* 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 #include "io.h" #include "../analysis/contents/memory.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_quick_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); afia_quick_exit: 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; } /****************************************************************************** * * * Paramètres : intput = archive dont le contenu est à extraire. * * entry = entrée de l'archive à extraire. * * * * Description : Extrait un élement d'une archive. * * * * Retour : Nouveau contenu volatile ou NULL en cas d'échec. * * * * Remarques : - * * * ******************************************************************************/ GBinContent *dump_archive_entry_into_memory(struct archive *input, struct archive_entry *entry) { GBinContent *result; /* Contenu à retourner */ bin_t *full_data; /* Données rassemblées */ phys_t full_size; /* Somme de toutes les tailles */ const void *buff; /* Tampon de copie */ size_t size; /* Quantité copiée */ __LA_INT64_T offset; /* Position de lecture */ int ret; /* Bilan d'un appel */ result = NULL; full_data = NULL; full_size = 0; for (ret = archive_read_data_block(input, &buff, &size, &offset); ret == ARCHIVE_OK; ret = archive_read_data_block(input, &buff, &size, &offset)) { full_data = realloc(full_data, full_size + size); memcpy(full_data + full_size, buff, size); full_size += size; } if (ret == ARCHIVE_EOF) result = g_memory_content_new(full_data, full_size); if (full_data != NULL) free(full_data); return result; }