Amélioration de l'interface de la ligne de commande
This commit is contained in:
		
							parent
							
								
									69f64a3fc5
								
							
						
					
					
						commit
						f5522c4036
					
				| 
						 | 
					@ -2,13 +2,8 @@
 | 
				
			||||||
#define __IN303_COMPRESS_H__
 | 
					#define __IN303_COMPRESS_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "huftree.h"
 | 
					#include "huftree.h"
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define COMPRESS_OK 0
 | 
					void compress(FILE* source, FILE* dest);
 | 
				
			||||||
#define COMPRESS_READ_ERROR 1
 | 
					 | 
				
			||||||
#define COMPRESS_WRITE_ERROR 2
 | 
					 | 
				
			||||||
#define COMPRESS_OPEN_INPUT_ERROR 3
 | 
					 | 
				
			||||||
#define COMPRESS_OPEN_OUTPUT_ERROR 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int compress(const char*, const char*);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
#define __IN303_HUFTREE_H__
 | 
					#define __IN303_HUFTREE_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include "buffer.h"
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -47,10 +48,10 @@ struct HufTree {
 | 
				
			||||||
HufTree createTree(double* frequencies);
 | 
					HufTree createTree(double* frequencies);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Écrit une représentation binaire de l'arbre dans le fichier
 | 
					 * Écrit une représentation binaire de l'arbre dans le
 | 
				
			||||||
 * passé en paramètre
 | 
					 * tampon passé en paramètre
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void writeTree(HufTree, FILE*);
 | 
					void writeTree(HufTree, Buffer*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Reconstruit un arbre de Huffman à partir du fichier passé
 | 
					 * Reconstruit un arbre de Huffman à partir du fichier passé
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ static double* _createFrequencies(FILE*);
 | 
				
			||||||
 * en suivant les étiquettes passées. Les étiquettes
 | 
					 * en suivant les étiquettes passées. Les étiquettes
 | 
				
			||||||
 * peuvent être calculées avec labelTree()
 | 
					 * peuvent être calculées avec labelTree()
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void _encodeFromTable(char**, FILE*, FILE*);
 | 
					void _encodeFromTable(char**, FILE*, Buffer*);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
double* _createFrequencies(FILE* file) {
 | 
					double* _createFrequencies(FILE* file) {
 | 
				
			||||||
    double* frequencies = malloc(NUM_CHARS * sizeof(*frequencies));
 | 
					    double* frequencies = malloc(NUM_CHARS * sizeof(*frequencies));
 | 
				
			||||||
| 
						 | 
					@ -49,12 +49,11 @@ double* _createFrequencies(FILE* file) {
 | 
				
			||||||
    return frequencies;
 | 
					    return frequencies;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void _encodeFromTable(char** labels, FILE* input, FILE* output) {
 | 
					void _encodeFromTable(char** labels, FILE* source, Buffer* output) {
 | 
				
			||||||
    Buffer buffer = createBuffer(output);
 | 
					 | 
				
			||||||
    int current;
 | 
					    int current;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Lecture du fichier d'entrée caractère par caractère
 | 
					    // Lecture du fichier d'entrée caractère par caractère
 | 
				
			||||||
    while ((current = fgetc(input)) != EOF) {
 | 
					    while ((current = fgetc(source)) != EOF) {
 | 
				
			||||||
        assert(current >= 0 && current < NUM_CHARS);
 | 
					        assert(current >= 0 && current < NUM_CHARS);
 | 
				
			||||||
        char* label = labels[current];
 | 
					        char* label = labels[current];
 | 
				
			||||||
        assert(label != NULL);
 | 
					        assert(label != NULL);
 | 
				
			||||||
| 
						 | 
					@ -62,40 +61,20 @@ void _encodeFromTable(char** labels, FILE* input, FILE* output) {
 | 
				
			||||||
        // Ajout du label dans le buffer, caractère par caractère
 | 
					        // Ajout du label dans le buffer, caractère par caractère
 | 
				
			||||||
        // vidant progressivement le buffer
 | 
					        // vidant progressivement le buffer
 | 
				
			||||||
        while (*label != '\0') {
 | 
					        while (*label != '\0') {
 | 
				
			||||||
            pushToBuffer(*label == '1', &buffer);
 | 
					            pushToBuffer(*label == '1', output);
 | 
				
			||||||
            label++;
 | 
					            label++;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Écriture du dernier octet dans le fichier
 | 
					 | 
				
			||||||
    // (pas toujours plein)
 | 
					 | 
				
			||||||
    flushBuffer(&buffer);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int compress(const char* inputpath, const char* outputpath) {
 | 
					void compress(FILE* source, FILE* dest) {
 | 
				
			||||||
    // FIXME: gérer le fichier vide
 | 
					    // FIXME: gérer le fichier vide
 | 
				
			||||||
    // FIXME: gérer les fichiers avec un seul type de caractère
 | 
					    // FIXME: gérer les fichiers ne contenant qu'un seul type de caractère
 | 
				
			||||||
 | 
					    // FIXME: gérer l'entrée depuis stdin (pas de double lecture)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printVerbose(
 | 
					    // Calcul de la clef de codage à partir de la source
 | 
				
			||||||
        "Compression du fichier '%s' en '%s'...\n",
 | 
					 | 
				
			||||||
        inputpath, outputpath
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Ouverture de l'entrée en lecture et la sortie en écriture
 | 
					 | 
				
			||||||
    FILE* input;
 | 
					 | 
				
			||||||
    FILE* output;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((input = fopen(inputpath, "r")) == NULL) {
 | 
					 | 
				
			||||||
        return COMPRESS_OPEN_INPUT_ERROR;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((output = fopen(outputpath, "w")) == NULL) {
 | 
					 | 
				
			||||||
        return COMPRESS_OPEN_OUTPUT_ERROR;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Comptage des caractères et calcul des fréquences d'apparition
 | 
					 | 
				
			||||||
    printVerbose("Calcul des fréquences d'apparition des caractères.\n");
 | 
					    printVerbose("Calcul des fréquences d'apparition des caractères.\n");
 | 
				
			||||||
    double* frequencies = _createFrequencies(input);
 | 
					    double* frequencies = _createFrequencies(source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (isVerbose()) {
 | 
					    if (isVerbose()) {
 | 
				
			||||||
        printFrequenciesTable(frequencies, NUM_CHARS);
 | 
					        printFrequenciesTable(frequencies, NUM_CHARS);
 | 
				
			||||||
| 
						 | 
					@ -118,19 +97,19 @@ int compress(const char* inputpath, const char* outputpath) {
 | 
				
			||||||
        printLabelsTable(labels, NUM_CHARS);
 | 
					        printLabelsTable(labels, NUM_CHARS);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Écriture des données compressées vers la sortie
 | 
				
			||||||
 | 
					    Buffer output = createBuffer(dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printVerbose("\nÉcriture de l'arbre dans la sortie.\n");
 | 
					    printVerbose("\nÉcriture de l'arbre dans la sortie.\n");
 | 
				
			||||||
    writeTree(tree, output);
 | 
					    writeTree(tree, &output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printVerbose("Écriture des données compressées du fichier.\n");
 | 
					    printVerbose("Écriture des données compressées du fichier.\n");
 | 
				
			||||||
    rewind(input);
 | 
					    rewind(source);
 | 
				
			||||||
    _encodeFromTable(labels, input, output);
 | 
					    _encodeFromTable(labels, source, &output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Vidage du dernier octet du tampon et nettoyage
 | 
				
			||||||
 | 
					    flushBuffer(&output);
 | 
				
			||||||
    freeTree(tree);
 | 
					    freeTree(tree);
 | 
				
			||||||
    freeTreeLabels(labels);
 | 
					    freeTreeLabels(labels);
 | 
				
			||||||
    labels = NULL;
 | 
					    labels = NULL;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    fclose(input);
 | 
					 | 
				
			||||||
    fclose(output);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return COMPRESS_OK;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -146,10 +146,8 @@ void _findMinimalVertices(
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void writeTree(HufTree tree, FILE* output) {
 | 
					void writeTree(HufTree tree, Buffer* buffer) {
 | 
				
			||||||
    Buffer buffer = createBuffer(output);
 | 
					    _writeVertex(*tree.root, buffer);
 | 
				
			||||||
    _writeVertex(*tree.root, &buffer);
 | 
					 | 
				
			||||||
    flushBuffer(&buffer);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void _writeVertex(HufVertex vertex, Buffer* buffer) {
 | 
					void _writeVertex(HufVertex vertex, Buffer* buffer) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										182
									
								
								src/main.c
								
								
								
								
							
							
						
						
									
										182
									
								
								src/main.c
								
								
								
								
							| 
						 | 
					@ -1,31 +1,19 @@
 | 
				
			||||||
#include "common.h"
 | 
					#include "common.h"
 | 
				
			||||||
#include "compress.h"
 | 
					#include "compress.h"
 | 
				
			||||||
#include <argp.h>
 | 
					#include <argp.h>
 | 
				
			||||||
 | 
					#include <libintl.h>
 | 
				
			||||||
#include <locale.h>
 | 
					#include <locale.h>
 | 
				
			||||||
#include <string.h>
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Définition de la configuration de Argp, qui affichera
 | 
					 | 
				
			||||||
 * ces informations dans la page d'aide entre autres
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
static char doc[] = "Compresse ou décompresse des fichiers en "
 | 
					 | 
				
			||||||
    "utilisant l'algorithme de Huffman";
 | 
					 | 
				
			||||||
static char args_doc[] = "FICHIER...";
 | 
					 | 
				
			||||||
static struct argp_option options[] = {
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        "verbose", 'V', 0, 0,
 | 
					 | 
				
			||||||
        "Afficher des informations de débogage sur la compression"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    {0}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Contient les valeurs des arguments (options et opérandes)
 | 
					 * Contient les valeurs des arguments (options et opérandes)
 | 
				
			||||||
 * passées au programme et interprétées via Argp
 | 
					 * passées au programme et interprétées via Argp
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct Args {
 | 
					typedef struct Args {
 | 
				
			||||||
    int verbose;
 | 
					    int verbose;
 | 
				
			||||||
    char** files;
 | 
					    int compress;
 | 
				
			||||||
 | 
					    FILE* source;
 | 
				
			||||||
 | 
					    FILE* dest;
 | 
				
			||||||
} Args;
 | 
					} Args;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -36,100 +24,118 @@ static error_t parse_opt(int key, char* arg, struct argp_state* state) {
 | 
				
			||||||
    Args* args = state->input;
 | 
					    Args* args = state->input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (key) {
 | 
					    switch (key) {
 | 
				
			||||||
        case 'V':
 | 
					    case 'v':
 | 
				
			||||||
        args->verbose = TRUE;
 | 
					        args->verbose = TRUE;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case ARGP_KEY_ARG:
 | 
					    case 'd':
 | 
				
			||||||
        // Consommation de tous les fichiers en argument
 | 
					        args->compress = FALSE;
 | 
				
			||||||
        // et arrêt du parsage
 | 
					 | 
				
			||||||
        args->files = &state->argv[state->next - 1];
 | 
					 | 
				
			||||||
        state->next = state->argc;
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case ARGP_KEY_NO_ARGS:
 | 
					    case ARGP_KEY_ARG:
 | 
				
			||||||
        argp_usage(state);
 | 
					        switch (state->arg_num) {
 | 
				
			||||||
        break;
 | 
					        case 0:
 | 
				
			||||||
 | 
					            // Premier argument : fichier d'entrée. Si omis,
 | 
				
			||||||
 | 
					            // utilisation de l'entrée standard
 | 
				
			||||||
 | 
					            args->source = fopen(arg, "r");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (args->source == NULL) {
 | 
				
			||||||
 | 
					                argp_error(
 | 
				
			||||||
 | 
					                    state, "%s: %s",
 | 
				
			||||||
 | 
					                    arg, strerror(errno)
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case 1:
 | 
				
			||||||
 | 
					            // Second argument : fichier de sortie. Si omis,
 | 
				
			||||||
 | 
					            // utilisation de la sortie standard
 | 
				
			||||||
 | 
					            args->dest = fopen(arg, "w");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (args->dest == NULL) {
 | 
				
			||||||
 | 
					                argp_error(
 | 
				
			||||||
 | 
					                    state, "%s: %s",
 | 
				
			||||||
 | 
					                    arg, strerror(errno)
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
 | 
					            argp_error(
 | 
				
			||||||
 | 
					                state, "Trop d'arguments - L'argument %s est superflu",
 | 
				
			||||||
 | 
					                arg
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
        return ARGP_ERR_UNKNOWN;
 | 
					        return ARGP_ERR_UNKNOWN;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct argp argp = {options, parse_opt, args_doc, doc};
 | 
					/**
 | 
				
			||||||
 | 
					 * Définition de la configuration de Argp, qui affichera
 | 
				
			||||||
 | 
					 * ces informations dans la page d'aide entre autres
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static struct argp_option options[] = {
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        .name = "decompress",
 | 
				
			||||||
 | 
					        .key = 'd',
 | 
				
			||||||
 | 
					        .doc = "Décompresse SOURCE vers DEST"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        .name = "verbose",
 | 
				
			||||||
 | 
					        .key = 'v',
 | 
				
			||||||
 | 
					        .doc = "Affiche des informations de débogage"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {0}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct argp argp = {
 | 
				
			||||||
 | 
					    .options = options,
 | 
				
			||||||
 | 
					    .parser = parse_opt,
 | 
				
			||||||
 | 
					    .args_doc = "[SOURCE [DEST]]",
 | 
				
			||||||
 | 
					    .doc = "Compresse ou décompresse SOURCE vers DEST en utilisant "
 | 
				
			||||||
 | 
					        "l'algorithme de Huffman (par défaut, compresse SOURCE vers DEST)."
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char** argv) {
 | 
					int main(int argc, char** argv) {
 | 
				
			||||||
    // Pour pouvoir afficher des caractères larges dans le terminal
 | 
					    // Paramètres de langue. Utilisation de la locale de l'utilisateur,
 | 
				
			||||||
    setlocale(LC_CTYPE, "");
 | 
					    // et des messages traduits dans libc (pour pallier à un bug de argp)
 | 
				
			||||||
 | 
					    setlocale(LC_ALL, "");
 | 
				
			||||||
 | 
					    textdomain("libc");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Interprétation des arguments passés au programme par Argv,
 | 
					    // Valeurs par défaut des arguments optionnels
 | 
				
			||||||
    // suivant la configuration définie au dessus
 | 
					    Args args = {
 | 
				
			||||||
    Args args;
 | 
					        .verbose = FALSE,
 | 
				
			||||||
 | 
					        .compress = TRUE,
 | 
				
			||||||
 | 
					        .source = stdin,
 | 
				
			||||||
 | 
					        .dest = stdout
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    args.verbose = FALSE;
 | 
					    // Interprétation des arguments passés au programme, résultat
 | 
				
			||||||
    args.files = NULL;
 | 
					    // dans `args`. Arrêt en cas d'erreur
 | 
				
			||||||
 | 
					    if (argp_parse(&argp, argc, argv, 0, 0, &args)) {
 | 
				
			||||||
    argp_parse(&argp, argc, argv, 0, 0, &args);
 | 
					        return EXIT_FAILURE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Passage en mode verbeux si demandé
 | 
					    // Passage en mode verbeux si demandé
 | 
				
			||||||
    setVerbose(args.verbose);
 | 
					    setVerbose(args.verbose);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Compression des fichiers en argument
 | 
					    // Compression ou décompression du flux d'entrée vers le flux de sortie
 | 
				
			||||||
    char** files = args.files;
 | 
					    if (args.compress) {
 | 
				
			||||||
 | 
					        compress(args.source, args.dest);
 | 
				
			||||||
    while (*files != NULL) {
 | 
					    } else {
 | 
				
			||||||
        char* input = *files;
 | 
					        fprintf(stderr, "Décompression non-implémentée.\n");
 | 
				
			||||||
 | 
					        return EXIT_FAILURE;
 | 
				
			||||||
        // Compression du fichier xx en xx.huf
 | 
					 | 
				
			||||||
        // TODO: rendre le nom du fichier de sortie configurable
 | 
					 | 
				
			||||||
        char* output = malloc((strlen(input) + 5) * sizeof(*output));
 | 
					 | 
				
			||||||
        strcpy(output, input);
 | 
					 | 
				
			||||||
        strcat(output, ".huf");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch (compress(input, output)) {
 | 
					 | 
				
			||||||
        case COMPRESS_READ_ERROR:
 | 
					 | 
				
			||||||
            fprintf(
 | 
					 | 
				
			||||||
                stderr,
 | 
					 | 
				
			||||||
                "Erreur : impossible de lire le fichier '%s' - %s\n",
 | 
					 | 
				
			||||||
                input, strerror(errno)
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            return COMPRESS_READ_ERROR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        case COMPRESS_WRITE_ERROR:
 | 
					 | 
				
			||||||
            fprintf(
 | 
					 | 
				
			||||||
                stderr,
 | 
					 | 
				
			||||||
                "Erreur : impossible d'écrire dans le fichier '%s' - %s\n",
 | 
					 | 
				
			||||||
                output, strerror(errno)
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            return COMPRESS_WRITE_ERROR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        case COMPRESS_OPEN_INPUT_ERROR:
 | 
					 | 
				
			||||||
            fprintf(
 | 
					 | 
				
			||||||
                stderr,
 | 
					 | 
				
			||||||
                "Erreur : impossible d'ouvrir le fichier '%s' - %s\n",
 | 
					 | 
				
			||||||
                input, strerror(errno)
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            return COMPRESS_OPEN_INPUT_ERROR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        case COMPRESS_OPEN_OUTPUT_ERROR:
 | 
					 | 
				
			||||||
            fprintf(
 | 
					 | 
				
			||||||
                stderr,
 | 
					 | 
				
			||||||
                "Erreur : impossible d'ouvrir le fichier '%s' - %s\n",
 | 
					 | 
				
			||||||
                output, strerror(errno)
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
            return COMPRESS_OPEN_OUTPUT_ERROR;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        free(output);
 | 
					 | 
				
			||||||
        files++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Ligne de séparation entre les différents fichiers
 | 
					 | 
				
			||||||
        if (*files != NULL) {
 | 
					 | 
				
			||||||
            printVerbose("\n");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fermeture des flux et sortie
 | 
				
			||||||
 | 
					    fclose(args.source);
 | 
				
			||||||
 | 
					    fclose(args.dest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return EXIT_SUCCESS;
 | 
					    return EXIT_SUCCESS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue