summaryrefslogtreecommitdiff
path: root/lib/sqfs/comp/gzip.c
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-01 22:42:49 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-09-01 22:42:49 +0200
commit307107ecd2fc3ffbf6fe91497daf767700f3572f (patch)
tree87c2c5993ab10cd4aa791a4e6d34f251db208ed2 /lib/sqfs/comp/gzip.c
parent2e28c45601a57b1d23e9cad33d2bdcc59e8a3f4f (diff)
Move command line processing stuff out of compressor code
This commit moves stuff like printing help text, command line option processing and enumerating available processors on stdout out of the generic compressor code. The option string is replaced with a structure that directly exposese the tweakable parameters for all compressors. A function for parsing the command line arguments into this structure is added in sqfshelper. Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
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);
-}