summaryrefslogtreecommitdiff
path: root/lib/sqfs/comp/xz.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/xz.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/xz.c')
-rw-r--r--lib/sqfs/comp/xz.c216
1 files changed, 55 insertions, 161 deletions
diff --git a/lib/sqfs/comp/xz.c b/lib/sqfs/comp/xz.c
index d38aab6..4f67b1c 100644
--- a/lib/sqfs/comp/xz.c
+++ b/lib/sqfs/comp/xz.c
@@ -15,17 +15,6 @@
#include "internal.h"
-typedef enum {
- XZ_FILTER_X86 = 0x01,
- XZ_FILTER_POWERPC = 0x02,
- XZ_FILTER_IA64 = 0x04,
- XZ_FILTER_ARM = 0x08,
- XZ_FILTER_ARMTHUMB = 0x10,
- XZ_FILTER_SPARC = 0x20,
-
- XZ_FILTER_ALL = 0x3F,
-} XZ_FILTER_FLAG;
-
typedef struct {
compressor_t base;
size_t block_size;
@@ -38,20 +27,15 @@ typedef struct {
uint32_t flags;
} xz_options_t;
-static const struct {
- const char *name;
- lzma_vli filter;
- int flag;
-} xz_filters[] = {
- { "x86", LZMA_FILTER_X86, XZ_FILTER_X86 },
- { "powerpc", LZMA_FILTER_POWERPC, XZ_FILTER_POWERPC },
- { "ia64", LZMA_FILTER_IA64, XZ_FILTER_IA64 },
- { "arm", LZMA_FILTER_ARM, XZ_FILTER_ARM },
- { "armthumb", LZMA_FILTER_ARMTHUMB, XZ_FILTER_ARMTHUMB },
- { "sparc", LZMA_FILTER_SPARC, XZ_FILTER_SPARC },
-};
-
-#define XZ_NUM_FILTERS (sizeof(xz_filters) / sizeof(xz_filters[0]))
+static bool is_dict_size_valid(size_t size)
+{
+ size_t x = size & (size - 1);
+
+ if (x == 0)
+ return true;
+
+ return size == (x | (x >> 1));
+}
static int xz_write_options(compressor_t *base, int fd)
{
@@ -71,7 +55,6 @@ static int xz_read_options(compressor_t *base, int fd)
{
xz_compressor_t *xz = (xz_compressor_t *)base;
xz_options_t opt;
- uint32_t mask;
if (generic_read_options(fd, &opt, sizeof(opt)))
return -1;
@@ -79,14 +62,12 @@ static int xz_read_options(compressor_t *base, int fd)
opt.dict_size = le32toh(opt.dict_size);
opt.flags = le32toh(opt.flags);
- mask = opt.dict_size & (opt.dict_size - 1);
-
- if (mask != 0 && ((mask & (mask - 1)) != 0)) {
+ if (!is_dict_size_valid(opt.dict_size)) {
fputs("Invalid lzma dictionary size.\n", stderr);
return -1;
}
- if (opt.flags & ~XZ_FILTER_ALL) {
+ if (opt.flags & ~SQFS_COMP_FLAG_XZ_ALL) {
fputs("Unknown BCJ filter used.\n", stderr);
return -1;
}
@@ -141,11 +122,31 @@ static ssize_t compress(xz_compressor_t *xz, lzma_vli filter,
return 0;
}
+static lzma_vli flag_to_vli(int flag)
+{
+ switch (flag) {
+ case SQFS_COMP_FLAG_XZ_X86:
+ return LZMA_FILTER_X86;
+ case SQFS_COMP_FLAG_XZ_POWERPC:
+ return LZMA_FILTER_POWERPC;
+ case SQFS_COMP_FLAG_XZ_IA64:
+ return LZMA_FILTER_IA64;
+ case SQFS_COMP_FLAG_XZ_ARM:
+ return LZMA_FILTER_ARM;
+ case SQFS_COMP_FLAG_XZ_ARMTHUMB:
+ return LZMA_FILTER_ARMTHUMB;
+ case SQFS_COMP_FLAG_XZ_SPARC:
+ return LZMA_FILTER_SPARC;
+ }
+
+ return LZMA_VLI_UNKNOWN;
+}
+
static ssize_t xz_comp_block(compressor_t *base, const uint8_t *in,
size_t size, uint8_t *out, size_t outsize)
{
xz_compressor_t *xz = (xz_compressor_t *)base;
- lzma_vli selected = LZMA_VLI_UNKNOWN;
+ lzma_vli filter, selected = LZMA_VLI_UNKNOWN;
size_t i, smallest;
ssize_t ret;
@@ -155,17 +156,19 @@ static ssize_t xz_comp_block(compressor_t *base, const uint8_t *in,
smallest = ret;
- for (i = 0; i < XZ_NUM_FILTERS; ++i) {
- if (!(xz->flags & xz_filters[i].flag))
+ for (i = 0; i & SQFS_COMP_FLAG_XZ_ALL; i <<= 1) {
+ if ((xz->flags & i) == 0)
continue;
- ret = compress(xz, xz_filters[i].filter, in, size, out, outsize);
+ filter = flag_to_vli(i);
+
+ ret = compress(xz, filter, in, size, out, outsize);
if (ret < 0)
return -1;
if (ret > 0 && (smallest == 0 || (size_t)ret < smallest)) {
smallest = ret;
- selected = xz_filters[i].filter;
+ selected = filter;
}
}
@@ -213,108 +216,22 @@ static void xz_destroy(compressor_t *base)
free(base);
}
-static int process_options(char *options, size_t blocksize,
- int *flags, uint64_t *dictsize)
-{
- enum {
- OPT_DICT = 0,
- };
- char *const token[] = {
- [OPT_DICT] = (char *)"dictsize",
- NULL
- };
- char *subopts, *value;
- uint64_t mask;
- size_t i;
- int opt;
-
- subopts = options;
-
- while (*subopts != '\0') {
- opt = getsubopt(&subopts, token, &value);
-
- switch (opt) {
- case OPT_DICT:
- if (value == NULL)
- goto fail_value;
-
- for (i = 0; isdigit(value[i]); ++i)
- ;
-
- if (i < 1 || i > 9)
- goto fail_dict;
-
- *dictsize = atol(value);
-
- switch (value[i]) {
- case '\0':
- break;
- case 'm':
- case 'M':
- *dictsize <<= 20;
- break;
- case 'k':
- case 'K':
- *dictsize <<= 10;
- break;
- case '%':
- *dictsize = ((*dictsize) * blocksize) / 100;
- break;
- default:
- goto fail_dict;
- }
-
- if (*dictsize > 0x0FFFFFFFFUL)
- goto fail_dict_ov;
-
- mask = *dictsize & (*dictsize - 1);
-
- if (mask != 0 && ((mask & (mask - 1)) != 0))
- goto fail_dict_pot;
- break;
- default:
- for (i = 0; i < XZ_NUM_FILTERS; ++i) {
- if (strcmp(value, xz_filters[i].name) == 0) {
- *flags |= xz_filters[i].flag;
- break;
- }
- }
- if (i == XZ_NUM_FILTERS)
- goto fail_opt;
- break;
- }
- }
-
- return 0;
-fail_dict_pot:
- fputs("dictionary size must be either 2^n or 2^n + 2^(n-1)\n", stderr);
- return -1;
-fail_dict_ov:
- fputs("dictionary size too large.\n", stderr);
- return -1;
-fail_dict:
- fputs("dictionary size must be a number with the optional "
- "suffix 'm','k' or '%'.\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;
-}
-
-compressor_t *create_xz_compressor(bool compress, size_t block_size,
- char *options)
+compressor_t *create_xz_compressor(const compressor_config_t *cfg)
{
- uint64_t dictsize = block_size;
xz_compressor_t *xz;
compressor_t *base;
- int flags = 0;
- if (options != NULL) {
- if (process_options(options, block_size, &flags, &dictsize))
- return NULL;
+ if (cfg->flags & ~(SQFS_COMP_FLAG_GENERIC_ALL |
+ SQFS_COMP_FLAG_XZ_ALL)) {
+ fputs("creating xz compressor: unknown compressor flags\n",
+ stderr);
+ return NULL;
+ }
+
+ if (!is_dict_size_valid(cfg->opt.xz.dict_size)) {
+ fputs("creating xz compressor: invalid dictionary size\n",
+ stderr);
+ return NULL;
}
xz = calloc(1, sizeof(*xz));
@@ -324,37 +241,14 @@ compressor_t *create_xz_compressor(bool compress, size_t block_size,
return NULL;
}
- xz->flags = flags;
- xz->dict_size = dictsize;
- xz->block_size = block_size;
+ xz->flags = cfg->flags;
+ xz->dict_size = cfg->opt.xz.dict_size;
+ xz->block_size = cfg->block_size;
base->destroy = xz_destroy;
- base->do_block = compress ? xz_comp_block : xz_uncomp_block;
+ base->do_block = (cfg->flags & SQFS_COMP_FLAG_UNCOMPRESS) ?
+ xz_uncomp_block : xz_comp_block;
base->write_options = xz_write_options;
base->read_options = xz_read_options;
base->create_copy = xz_create_copy;
return base;
}
-
-void compressor_xz_print_help(void)
-{
- size_t i;
-
- fputs(
-"Available options for xz compressor:\n"
-"\n"
-" dictsize=<value> Dictionary size. Either a value in bytes or a\n"
-" percentage of the block size. Defaults to 100%.\n"
-" The suffix '%' indicates a percentage. 'K' and 'M'\n"
-" can also be used for kibi and mebi bytes\n"
-" respecitively.\n"
-"\n"
-"In additon to the options, one or more bcj filters can be specified.\n"
-"If multiple filters are provided, the one yielding the best compression\n"
-"ratio will be used.\n"
-"\n"
-"The following filters are available:\n",
- stdout);
-
- for (i = 0; i < XZ_NUM_FILTERS; ++i)
- printf("\t%s\n", xz_filters[i].name);
-}