From e378fd8cbb69892d0af4110a7e3968d074700769 Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Fri, 17 Jul 2026 20:32:44 +0200 Subject: Beispiel für gzip-Dateien hinzugefügt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- makefile | 10 ++++- src/gzip.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 2 deletions(-) create mode 100644 src/gzip.c diff --git a/makefile b/makefile index 312721e..6ad412d 100644 --- a/makefile +++ b/makefile @@ -6,10 +6,13 @@ STREAM_OBJ_FILES=obj/stream.o SIMPLE=bin/simple SIMPLE_OBJ_FILES=obj/simple.o -release: $(STREAM) $(SIMPLE) +GZIP=bin/gzip +GZIP_OBJ_FILES=obj/gzip.o + +release: $(STREAM) $(SIMPLE) $(GZIP) release: CFLAGS+=-DNDEBUG -O2 -debug: $(STREAM) $(SIMPLE) +debug: $(STREAM) $(SIMPLE) $(GZIP) debug: CFLAGS+=-g $(STREAM): $(STREAM_OBJ_FILES) | bin @@ -18,6 +21,9 @@ $(STREAM): $(STREAM_OBJ_FILES) | bin $(SIMPLE): $(SIMPLE_OBJ_FILES) | bin cc $(LDFLAGS) $^ -o $@ +$(GZIP): $(GZIP_OBJ_FILES) | bin + cc $(LDFLAGS) $^ -o $@ + obj/%.o: src/%.c | obj cc $(CFLAGS) -c $< -o $@ diff --git a/src/gzip.c b/src/gzip.c new file mode 100644 index 0000000..11828db --- /dev/null +++ b/src/gzip.c @@ -0,0 +1,125 @@ +// Standard C +#include +#include +#include +#include + +// System +#include + +// zlib +#include + +enum { BUFFER_SIZE = 8192 }; + +static void +usage(void) +{ + (void) fprintf(stderr, "stream [-d] infile outfile\n"); +} + +static void +error(const char *msg) +{ + perror(msg); + exit(EXIT_FAILURE); +} + +void +do_compress(const char *in_name, const char *out_name, int compress_level) +{ + FILE *in_file = fopen(in_name, "rb"); + if ( in_file == NULL ) { + error("fopen() on in_file failed"); + } + + char mode[10]; + (void) snprintf(mode, sizeof mode, "wb%d", compress_level); + + gzFile out_file = gzopen(out_name, mode); + if ( out_file == NULL ) { + (void) fclose(in_file); + error("gzopen() on out_file failed"); + } + + unsigned char buffer[BUFFER_SIZE]; + + size_t bytes_read = 0; + while ( (bytes_read = fread(buffer, 1, BUFFER_SIZE, in_file)) != 0 ) { + gzfwrite(buffer, 1, bytes_read, out_file); + } + + (void) fclose(in_file); + gzclose(out_file); +} + +void +do_uncompress(const char *in_name, const char *out_name) +{ + gzFile in_file = gzopen(in_name, "rb"); + if ( in_file == NULL ) { + error("gzopen() on in_file failed"); + } + + FILE *out_file = fopen(out_name, "wb"); + if ( out_file == NULL ) { + (void) gzclose(in_file); + error("fopen() on out_file failed"); + } + + unsigned char buffer[BUFFER_SIZE]; + + size_t bytes_read = 0; + while ( (bytes_read = gzfread(buffer, 1, BUFFER_SIZE, in_file)) != 0 ) { + (void) fwrite(buffer, 1, bytes_read, out_file); + } + + gzclose(in_file); + (void) fclose(out_file); +} + +int +main(int argc, char *argv[]) +{ + enum { + COMPRESSION_STD = 5, + COMPRESSION_BEST = 9 + }; + + int decompress = 0; + int compress_level = COMPRESSION_STD; + + int opt = 0; + while ( (opt = getopt(argc, argv, "dl")) != -1 ) { + switch ( opt ) { + case 'd': + decompress = 1; + break; + + case 'l': + compress_level = COMPRESSION_BEST; + break; + + case '?': + default: + usage(); + return EXIT_SUCCESS; + } + } + argc -= optind; + argv += optind; + + if ( argc != 2 ) { + usage(); + return EXIT_FAILURE; + } + + if ( !decompress ) { + do_compress(argv[0], argv[1], compress_level); + } + else { + do_uncompress(argv[0], argv[1]); + } + + return EXIT_SUCCESS; +} -- cgit v1.3