summaryrefslogtreecommitdiff
path: root/lib/comp/gzip.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/comp/gzip.c')
-rw-r--r--lib/comp/gzip.c412
1 files changed, 0 insertions, 412 deletions
diff --git a/lib/comp/gzip.c b/lib/comp/gzip.c
deleted file mode 100644
index 1fdc051..0000000
--- a/lib/comp/gzip.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * gzip.c
- *
- * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <zlib.h>
-
-#include "internal.h"
-
-#define GZIP_DEFAULT_LEVEL 9
-#define GZIP_DEFAULT_WINDOW 15
-#define GZIP_NUM_STRATEGIES (sizeof(strategies) / sizeof(strategies[0]))
-
-typedef enum {
- GZIP_STRATEGY_DEFAULT = 0x01,
- GZIP_STRATEGY_FILTERED = 0x02,
- GZIP_STRATEGY_HUFFMAN = 0x04,
- GZIP_STARTEGY_RLE = 0x08,
- GZIP_STRATEGY_FIXED = 0x10,
-
- GZIP_ALL_STRATEGIES = 0x1F,
-} GZIP_STRATEGIES;
-
-static const struct {
- const char *name;
- int flag;
- int zlib;
-} strategies[] = {
- { "default", GZIP_STRATEGY_DEFAULT, Z_DEFAULT_STRATEGY },
- { "filtered", GZIP_STRATEGY_FILTERED, Z_FILTERED },
- { "huffman", GZIP_STRATEGY_HUFFMAN, Z_HUFFMAN_ONLY },
- { "rle", GZIP_STARTEGY_RLE, Z_RLE },
- { "fixed", GZIP_STRATEGY_FIXED, Z_FIXED },
-};
-
-typedef struct {
- uint32_t level;
- uint16_t window;
- uint16_t strategies;
-} gzip_options_t;
-
-typedef struct {
- compressor_t base;
-
- z_stream strm;
- bool compress;
-
- size_t block_size;
- gzip_options_t opt;
-} gzip_compressor_t;
-
-static void gzip_destroy(compressor_t *base)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
-
- if (gzip->compress) {
- deflateEnd(&gzip->strm);
- } else {
- inflateEnd(&gzip->strm);
- }
-
- free(gzip);
-}
-
-static int gzip_write_options(compressor_t *base, int fd)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
- gzip_options_t opt;
-
- if (gzip->opt.level == GZIP_DEFAULT_LEVEL &&
- gzip->opt.window == GZIP_DEFAULT_WINDOW &&
- gzip->opt.strategies == 0) {
- return 0;
- }
-
- opt.level = htole32(gzip->opt.level);
- opt.window = htole16(gzip->opt.window);
- opt.strategies = htole16(gzip->opt.strategies);
-
- return generic_write_options(fd, &opt, sizeof(opt));
-}
-
-static int gzip_read_options(compressor_t *base, int fd)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
- gzip_options_t opt;
-
- if (generic_read_options(fd, &opt, sizeof(opt)))
- return -1;
-
- gzip->opt.level = le32toh(opt.level);
- gzip->opt.window = le16toh(opt.window);
- gzip->opt.strategies = le16toh(opt.strategies);
-
- if (gzip->opt.level < 1 || gzip->opt.level > 9) {
- fprintf(stderr, "Invalid gzip compression level '%d'.\n",
- gzip->opt.level);
- return -1;
- }
-
- if (gzip->opt.window < 8 || gzip->opt.window > 15) {
- fprintf(stderr, "Invalid gzip window size '%d'.\n",
- gzip->opt.window);
- return -1;
- }
-
- if (gzip->opt.strategies & ~GZIP_ALL_STRATEGIES) {
- fputs("Unknown gzip strategies selected.\n", stderr);
- return -1;
- }
-
- return 0;
-}
-
-static int find_strategy(gzip_compressor_t *gzip, const uint8_t *in,
- size_t size, uint8_t *out, size_t outsize)
-{
- int ret, selected = Z_DEFAULT_STRATEGY;
- size_t i, length, minlength = 0;
-
- for (i = 0; i < GZIP_NUM_STRATEGIES; ++i) {
- if (!(strategies[i].flag & gzip->opt.strategies))
- continue;
-
- ret = deflateReset(&gzip->strm);
- if (ret != Z_OK) {
- fputs("resetting zlib stream failed\n",
- stderr);
- return -1;
- }
-
- gzip->strm.next_in = (void *)in;
- gzip->strm.avail_in = size;
- gzip->strm.next_out = out;
- gzip->strm.avail_out = outsize;
-
- ret = deflateParams(&gzip->strm, gzip->opt.level,
- strategies[i].zlib);
- if (ret != Z_OK) {
- fputs("setting deflate parameters failed\n",
- stderr);
- return -1;
- }
-
- ret = deflate(&gzip->strm, Z_FINISH);
-
- if (ret == Z_STREAM_END) {
- length = gzip->strm.total_out;
-
- if (minlength == 0 || length < minlength) {
- minlength = length;
- selected = strategies[i].zlib;
- }
- } else if (ret != Z_OK && ret != Z_BUF_ERROR) {
- fputs("gzip block processing failed\n", stderr);
- return -1;
- }
- }
-
- return selected;
-}
-
-static ssize_t gzip_do_block(compressor_t *base, const uint8_t *in,
- size_t size, uint8_t *out, size_t outsize)
-{
- gzip_compressor_t *gzip = (gzip_compressor_t *)base;
- int ret, strategy = 0;
- size_t written;
-
- if (gzip->compress && gzip->opt.strategies != 0) {
- strategy = find_strategy(gzip, in, size, out, outsize);
- if (strategy < 0)
- return -1;
- }
-
- if (gzip->compress) {
- ret = deflateReset(&gzip->strm);
- } else {
- ret = inflateReset(&gzip->strm);
- }
-
- if (ret != Z_OK) {
- fputs("resetting zlib stream failed\n", stderr);
- return -1;
- }
-
- gzip->strm.next_in = (void *)in;
- gzip->strm.avail_in = size;
- gzip->strm.next_out = out;
- gzip->strm.avail_out = outsize;
-
- if (gzip->compress && gzip->opt.strategies != 0) {
- ret = deflateParams(&gzip->strm, gzip->opt.level, strategy);
- if (ret != Z_OK) {
- fputs("setting selcted deflate parameters failed\n",
- stderr);
- return -1;
- }
- }
-
- if (gzip->compress) {
- ret = deflate(&gzip->strm, Z_FINISH);
- } else {
- ret = inflate(&gzip->strm, Z_FINISH);
- }
-
- if (ret == Z_STREAM_END) {
- written = gzip->strm.total_out;
-
- if (gzip->compress && written >= size)
- return 0;
-
- return (ssize_t)written;
- }
-
- if (ret != Z_OK && ret != Z_BUF_ERROR) {
- fputs("gzip block processing failed\n", stderr);
- return -1;
- }
-
- return 0;
-}
-
-static int process_options(char *options, int *level, int *window, int *flags)
-{
- enum {
- OPT_WINDOW = 0,
- OPT_LEVEL,
- };
- char *const token[] = {
- [OPT_WINDOW] = (char *)"window",
- [OPT_LEVEL] = (char *)"level",
- NULL
- };
- char *subopts, *value;
- size_t i;
- int opt;
-
- subopts = options;
-
- while (*subopts != '\0') {
- opt = getsubopt(&subopts, token, &value);
-
- switch (opt) {
- case OPT_WINDOW:
- if (value == NULL)
- goto fail_value;
-
- for (i = 0; isdigit(value[i]); ++i)
- ;
-
- if (i < 1 || i > 3 || value[i] != '\0')
- goto fail_window;
-
- *window = atoi(value);
-
- if (*window < 8 || *window > 15)
- goto fail_window;
- break;
- case OPT_LEVEL:
- if (value == NULL)
- goto fail_value;
-
- for (i = 0; isdigit(value[i]); ++i)
- ;
-
- if (i < 1 || i > 3 || value[i] != '\0')
- goto fail_level;
-
- *level = atoi(value);
-
- if (*level < 1 || *level > 9)
- goto fail_level;
- break;
- default:
- for (i = 0; i < GZIP_NUM_STRATEGIES; ++i) {
- if (strcmp(value, strategies[i].name) == 0) {
- *flags |= strategies[i].flag;
- break;
- }
- }
- if (i == GZIP_NUM_STRATEGIES)
- goto fail_opt;
- break;
- }
- }
-
- return 0;
-fail_window:
- fputs("Window size must be a number between 8 and 15.\n", stderr);
- return -1;
-fail_level:
- fputs("Compression level must be a number between 1 and 9.\n", stderr);
- return -1;
-fail_opt:
- fprintf(stderr, "Unknown option '%s'.\n", value);
- return -1;
-fail_value:
- fprintf(stderr, "Missing value for '%s'.\n", token[opt]);
- return -1;
-}
-
-static compressor_t *gzip_create_copy(compressor_t *cmp)
-{
- gzip_compressor_t *gzip = malloc(sizeof(*gzip));
- int ret;
-
- if (gzip == NULL) {
- perror("creating additional gzip compressor");
- return NULL;
- }
-
- memcpy(gzip, cmp, sizeof(*gzip));
- memset(&gzip->strm, 0, sizeof(gzip->strm));
-
- if (gzip->compress) {
- ret = deflateInit2(&gzip->strm, gzip->opt.level, Z_DEFLATED,
- gzip->opt.window, 8, Z_DEFAULT_STRATEGY);
- } else {
- ret = inflateInit(&gzip->strm);
- }
-
- if (ret != Z_OK) {
- fputs("internal error creating additional zlib stream\n",
- stderr);
- free(gzip);
- return NULL;
- }
-
- return (compressor_t *)gzip;
-}
-
-compressor_t *create_gzip_compressor(bool compress, size_t block_size,
- char *options)
-{
- int window = GZIP_DEFAULT_WINDOW;
- int level = GZIP_DEFAULT_LEVEL;
- gzip_compressor_t *gzip;
- compressor_t *base;
- int flags = 0;
- int ret;
-
- if (options != NULL) {
- if (process_options(options, &level, &window, &flags))
- return NULL;
- }
-
- gzip = calloc(1, sizeof(*gzip));
- base = (compressor_t *)gzip;
-
- if (gzip == NULL) {
- perror("creating gzip compressor");
- return NULL;
- }
-
- gzip->opt.level = level;
- gzip->opt.window = window;
- gzip->opt.strategies = flags;
- gzip->compress = compress;
- gzip->block_size = block_size;
- base->do_block = gzip_do_block;
- base->destroy = gzip_destroy;
- base->write_options = gzip_write_options;
- base->read_options = gzip_read_options;
- base->create_copy = gzip_create_copy;
-
- if (compress) {
- ret = deflateInit2(&gzip->strm, level, Z_DEFLATED, window, 8,
- Z_DEFAULT_STRATEGY);
- } else {
- ret = inflateInit(&gzip->strm);
- }
-
- if (ret != Z_OK) {
- fputs("internal error creating zlib stream\n", stderr);
- free(gzip);
- return NULL;
- }
-
- return base;
-}
-
-void compressor_gzip_print_help(void)
-{
- size_t i;
-
- printf(
-"Available options for gzip compressor:\n"
-"\n"
-" level=<value> Compression level. Value from 1 to 9.\n"
-" Defaults to %d.\n"
-" window=<size> Deflate compression window size. Value from 8 to 15.\n"
-" Defaults to %d.\n"
-"\n"
-"In additon to the options, one or more strategies can be specified.\n"
-"If multiple stratgies are provided, the one yielding the best compression\n"
-"ratio will be used.\n"
-"\n"
-"The following strategies are available:\n",
- GZIP_DEFAULT_LEVEL, GZIP_DEFAULT_WINDOW);
-
- for (i = 0; i < GZIP_NUM_STRATEGIES; ++i)
- printf("\t%s\n", strategies[i].name);
-}