summaryrefslogtreecommitdiff
path: root/lib/sqfs/comp/gzip.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/comp/gzip.c')
-rw-r--r--lib/sqfs/comp/gzip.c210
1 files changed, 58 insertions, 152 deletions
diff --git a/lib/sqfs/comp/gzip.c b/lib/sqfs/comp/gzip.c
index 1fdc051..bbe1e4f 100644
--- a/lib/sqfs/comp/gzip.c
+++ b/lib/sqfs/comp/gzip.c
@@ -15,32 +15,6 @@
#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;
@@ -75,8 +49,8 @@ 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 &&
+ if (gzip->opt.level == SQFS_GZIP_DEFAULT_LEVEL &&
+ gzip->opt.window == SQFS_GZIP_DEFAULT_WINDOW &&
gzip->opt.strategies == 0) {
return 0;
}
@@ -112,7 +86,7 @@ static int gzip_read_options(compressor_t *base, int fd)
return -1;
}
- if (gzip->opt.strategies & ~GZIP_ALL_STRATEGIES) {
+ if (gzip->opt.strategies & ~SQFS_COMP_FLAG_GZIP_ALL) {
fputs("Unknown gzip strategies selected.\n", stderr);
return -1;
}
@@ -120,14 +94,32 @@ static int gzip_read_options(compressor_t *base, int fd)
return 0;
}
+static int flag_to_zlib_strategy(int flag)
+{
+ switch (flag) {
+ case SQFS_COMP_FLAG_GZIP_DEFAULT:
+ return Z_DEFAULT_STRATEGY;
+ case SQFS_COMP_FLAG_GZIP_FILTERED:
+ return Z_FILTERED;
+ case SQFS_COMP_FLAG_GZIP_HUFFMAN:
+ return Z_HUFFMAN_ONLY;
+ case SQFS_COMP_FLAG_GZIP_RLE:
+ return Z_RLE;
+ case SQFS_COMP_FLAG_GZIP_FIXED:
+ return Z_FIXED;
+ }
+
+ 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;
+ int ret, strategy, 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))
+ for (i = 0x01; i & SQFS_COMP_FLAG_GZIP_ALL; i <<= 1) {
+ if ((gzip->opt.strategies & i) == 0)
continue;
ret = deflateReset(&gzip->strm);
@@ -137,13 +129,14 @@ static int find_strategy(gzip_compressor_t *gzip, const uint8_t *in,
return -1;
}
+ strategy = flag_to_zlib_strategy(i);
+
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);
+ ret = deflateParams(&gzip->strm, gzip->opt.level, strategy);
if (ret != Z_OK) {
fputs("setting deflate parameters failed\n",
stderr);
@@ -157,7 +150,7 @@ static int find_strategy(gzip_compressor_t *gzip, const uint8_t *in,
if (minlength == 0 || length < minlength) {
minlength = length;
- selected = strategies[i].zlib;
+ selected = strategy;
}
} else if (ret != Z_OK && ret != Z_BUF_ERROR) {
fputs("gzip block processing failed\n", stderr);
@@ -229,85 +222,6 @@ static ssize_t gzip_do_block(compressor_t *base, const uint8_t *in,
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));
@@ -338,19 +252,33 @@ static compressor_t *gzip_create_copy(compressor_t *cmp)
return (compressor_t *)gzip;
}
-compressor_t *create_gzip_compressor(bool compress, size_t block_size,
- char *options)
+compressor_t *create_gzip_compressor(const compressor_config_t *cfg)
{
- 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;
+ if (cfg->flags & ~(SQFS_COMP_FLAG_GZIP_ALL |
+ SQFS_COMP_FLAG_GENERIC_ALL)) {
+ fputs("creating gzip compressor: unknown compressor flags\n",
+ stderr);
+ return NULL;
+ }
+
+ if (cfg->opt.gzip.level < SQFS_GZIP_MIN_LEVEL ||
+ cfg->opt.gzip.level > SQFS_GZIP_MAX_LEVEL) {
+ fprintf(stderr, "creating gzip compressor: compression level"
+ "must be between %d and %d inclusive\n",
+ SQFS_GZIP_MIN_LEVEL, SQFS_GZIP_MAX_LEVEL);
+ return NULL;
+ }
+
+ if (cfg->opt.gzip.window_size < SQFS_GZIP_MIN_WINDOW ||
+ cfg->opt.gzip.window_size > SQFS_GZIP_MAX_WINDOW) {
+ fprintf(stderr, "creating gzip compressor: window size"
+ "must be between %d and %d inclusive\n",
+ SQFS_GZIP_MIN_WINDOW, SQFS_GZIP_MAX_WINDOW);
+ return NULL;
}
gzip = calloc(1, sizeof(*gzip));
@@ -361,19 +289,20 @@ compressor_t *create_gzip_compressor(bool compress, size_t block_size,
return NULL;
}
- gzip->opt.level = level;
- gzip->opt.window = window;
- gzip->opt.strategies = flags;
- gzip->compress = compress;
- gzip->block_size = block_size;
+ gzip->opt.level = cfg->opt.gzip.level;
+ gzip->opt.window = cfg->opt.gzip.window_size;
+ gzip->opt.strategies = cfg->flags & SQFS_COMP_FLAG_GZIP_ALL;
+ gzip->compress = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) == 0;
+ gzip->block_size = cfg->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,
+ if (gzip->compress) {
+ ret = deflateInit2(&gzip->strm, cfg->opt.gzip.level,
+ Z_DEFLATED, cfg->opt.gzip.window_size, 8,
Z_DEFAULT_STRATEGY);
} else {
ret = inflateInit(&gzip->strm);
@@ -387,26 +316,3 @@ compressor_t *create_gzip_compressor(bool compress, size_t block_size,
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);
-}