From c9d3c2e1628e5b28a553ae098b3b9f3019c45a63 Mon Sep 17 00:00:00 2001
From: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Date: Tue, 21 May 2019 12:16:37 +0200
Subject: Add command line flag for compressor options, pass them to
 compressors

Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
---
 include/compress.h    |  4 +++-
 lib/comp/compressor.c | 38 +++++++++++++++++++++++++++++++++++---
 lib/comp/gzip.c       |  7 ++++++-
 lib/comp/internal.h   | 25 ++++++++++++++++++++-----
 lib/comp/lz4.c        |  7 ++++++-
 lib/comp/lzo.c        |  7 ++++++-
 lib/comp/xz.c         |  7 ++++++-
 lib/comp/zstd.c       |  7 ++++++-
 mkfs/mkfs.c           |  9 ++++++++-
 mkfs/mkfs.h           |  1 +
 mkfs/options.c        | 11 +++++++++--
 unpack/rdsquashfs.c   |  2 +-
 12 files changed, 107 insertions(+), 18 deletions(-)

diff --git a/include/compress.h b/include/compress.h
index 4c1ec8b..5f13bc6 100644
--- a/include/compress.h
+++ b/include/compress.h
@@ -45,6 +45,8 @@ bool compressor_exists(E_SQFS_COMPRESSOR id);
 /* block_size is the configured block size for the SquashFS image. Needed
    by some compressors to set internal defaults. */
 compressor_t *compressor_create(E_SQFS_COMPRESSOR id, bool compress,
-				size_t block_size);
+				size_t block_size, char *options);
+
+void compressor_print_help(E_SQFS_COMPRESSOR id);
 
 #endif /* COMPRESS_H */
diff --git a/lib/comp/compressor.c b/lib/comp/compressor.c
index 369cbea..44b3643 100644
--- a/lib/comp/compressor.c
+++ b/lib/comp/compressor.c
@@ -5,7 +5,10 @@
 #include "internal.h"
 #include "util.h"
 
-typedef compressor_t *(*compressor_fun_t)(bool compress, size_t block_size);
+typedef compressor_t *(*compressor_fun_t)(bool compress, size_t block_size,
+					  char *options);
+
+typedef void (*compressor_help_fun_t)(void);
 
 static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = {
 #ifdef WITH_GZIP
@@ -25,6 +28,24 @@ static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = {
 #endif
 };
 
+static const compressor_help_fun_t helpfuns[SQFS_COMP_MAX + 1] = {
+#ifdef WITH_GZIP
+	[SQFS_COMP_GZIP] = compressor_gzip_print_help,
+#endif
+#ifdef WITH_XZ
+	[SQFS_COMP_XZ] = compressor_xz_print_help,
+#endif
+#ifdef WITH_LZO
+	[SQFS_COMP_LZO] = compressor_lzo_print_help,
+#endif
+#ifdef WITH_LZ4
+	[SQFS_COMP_LZ4] = compressor_lz4_print_help,
+#endif
+#ifdef WITH_ZSTD
+	[SQFS_COMP_ZSTD] = compressor_zstd_print_help,
+#endif
+};
+
 int generic_write_options(int fd, const void *data, size_t size)
 {
 	uint8_t buffer[size + 2];
@@ -85,7 +106,7 @@ bool compressor_exists(E_SQFS_COMPRESSOR id)
 }
 
 compressor_t *compressor_create(E_SQFS_COMPRESSOR id, bool compress,
-				size_t block_size)
+				size_t block_size, char *options)
 {
 	if (id < SQFS_COMP_MIN || id > SQFS_COMP_MAX)
 		return NULL;
@@ -93,5 +114,16 @@ compressor_t *compressor_create(E_SQFS_COMPRESSOR id, bool compress,
 	if (compressors[id] == NULL)
 		return NULL;
 
-	return compressors[id](compress, block_size);
+	return compressors[id](compress, block_size, options);
+}
+
+void compressor_print_help(E_SQFS_COMPRESSOR id)
+{
+	if (id < SQFS_COMP_MIN || id > SQFS_COMP_MAX)
+		return;
+
+	if (compressors[id] == NULL)
+		return;
+
+	helpfuns[id]();
 }
diff --git a/lib/comp/gzip.c b/lib/comp/gzip.c
index ea86f98..bc70bcf 100644
--- a/lib/comp/gzip.c
+++ b/lib/comp/gzip.c
@@ -90,7 +90,8 @@ static ssize_t gzip_do_block(compressor_t *base, const uint8_t *in,
 	return 0;
 }
 
-compressor_t *create_gzip_compressor(bool compress, size_t block_size)
+compressor_t *create_gzip_compressor(bool compress, size_t block_size,
+				     char *options)
 {
 	gzip_compressor_t *gzip = calloc(1, sizeof(*gzip));
 	compressor_t *base = (compressor_t *)gzip;
@@ -122,3 +123,7 @@ compressor_t *create_gzip_compressor(bool compress, size_t block_size)
 
 	return base;
 }
+
+void compressor_gzip_print_help(void)
+{
+}
diff --git a/lib/comp/internal.h b/lib/comp/internal.h
index 8f880f4..0185f4d 100644
--- a/lib/comp/internal.h
+++ b/lib/comp/internal.h
@@ -8,14 +8,29 @@ int generic_write_options(int fd, const void *data, size_t size);
 
 int generic_read_options(int fd, void *data, size_t size);
 
-compressor_t *create_xz_compressor(bool compress, size_t block_size);
+compressor_t *create_xz_compressor(bool compress, size_t block_size,
+				   char *options);
 
-compressor_t *create_gzip_compressor(bool compress, size_t block_size);
+compressor_t *create_gzip_compressor(bool compress, size_t block_size,
+				     char *options);
 
-compressor_t *create_lzo_compressor(bool compress, size_t block_size);
+compressor_t *create_lzo_compressor(bool compress, size_t block_size,
+				    char *options);
 
-compressor_t *create_lz4_compressor(bool compress, size_t block_size);
+compressor_t *create_lz4_compressor(bool compress, size_t block_size,
+				    char *options);
 
-compressor_t *create_zstd_compressor(bool compress, size_t block_size);
+compressor_t *create_zstd_compressor(bool compress, size_t block_size,
+				     char *options);
+
+void compressor_xz_print_help(void);
+
+void compressor_gzip_print_help(void);
+
+void compressor_lzo_print_help(void);
+
+void compressor_lz4_print_help(void);
+
+void compressor_zstd_print_help(void);
 
 #endif /* INTERNAL_H */
diff --git a/lib/comp/lz4.c b/lib/comp/lz4.c
index f9c753d..63ed528 100644
--- a/lib/comp/lz4.c
+++ b/lib/comp/lz4.c
@@ -87,7 +87,8 @@ static void lz4_destroy(compressor_t *base)
 	free(base);
 }
 
-compressor_t *create_lz4_compressor(bool compress, size_t block_size)
+compressor_t *create_lz4_compressor(bool compress, size_t block_size,
+				    char *options)
 {
 	lz4_compressor_t *lz4 = calloc(1, sizeof(*lz4));
 	compressor_t *base = (compressor_t *)lz4;
@@ -104,3 +105,7 @@ compressor_t *create_lz4_compressor(bool compress, size_t block_size)
 	base->read_options = lz4_read_options;
 	return base;
 }
+
+void compressor_lz4_print_help(void)
+{
+}
diff --git a/lib/comp/lzo.c b/lib/comp/lzo.c
index 95ab485..a7b6876 100644
--- a/lib/comp/lzo.c
+++ b/lib/comp/lzo.c
@@ -69,7 +69,8 @@ static void lzo_destroy(compressor_t *base)
 	free(base);
 }
 
-compressor_t *create_lzo_compressor(bool compress, size_t block_size)
+compressor_t *create_lzo_compressor(bool compress, size_t block_size,
+				    char *options)
 {
 	lzo_compressor_t *lzo = calloc(1, sizeof(*lzo));
 	compressor_t *base = (compressor_t *)lzo;
@@ -86,3 +87,7 @@ compressor_t *create_lzo_compressor(bool compress, size_t block_size)
 	base->read_options = lzo_read_options;
 	return base;
 }
+
+void compressor_lzo_print_help(void)
+{
+}
diff --git a/lib/comp/xz.c b/lib/comp/xz.c
index dd608ba..3fb3c12 100644
--- a/lib/comp/xz.c
+++ b/lib/comp/xz.c
@@ -88,7 +88,8 @@ static void xz_destroy(compressor_t *base)
 	free(base);
 }
 
-compressor_t *create_xz_compressor(bool compress, size_t block_size)
+compressor_t *create_xz_compressor(bool compress, size_t block_size,
+				   char *options)
 {
 	xz_compressor_t *xz = calloc(1, sizeof(*xz));
 	compressor_t *base = (compressor_t *)xz;
@@ -105,3 +106,7 @@ compressor_t *create_xz_compressor(bool compress, size_t block_size)
 	base->read_options = xz_read_options;
 	return base;
 }
+
+void compressor_xz_print_help(void)
+{
+}
diff --git a/lib/comp/zstd.c b/lib/comp/zstd.c
index 6c90505..4cbef38 100644
--- a/lib/comp/zstd.c
+++ b/lib/comp/zstd.c
@@ -69,7 +69,8 @@ static void zstd_destroy(compressor_t *base)
 	free(zstd);
 }
 
-compressor_t *create_zstd_compressor(bool compress, size_t block_size)
+compressor_t *create_zstd_compressor(bool compress, size_t block_size,
+				     char *options)
 {
 	zstd_compressor_t *zstd = calloc(1, sizeof(*zstd));
 	compressor_t *base = (compressor_t *)zstd;
@@ -93,3 +94,7 @@ compressor_t *create_zstd_compressor(bool compress, size_t block_size)
 	base->read_options = zstd_read_options;
 	return base;
 }
+
+void compressor_zstd_print_help(void)
+{
+}
diff --git a/mkfs/mkfs.c b/mkfs/mkfs.c
index dac0a34..c958d73 100644
--- a/mkfs/mkfs.c
+++ b/mkfs/mkfs.c
@@ -47,6 +47,12 @@ int main(int argc, char **argv)
 
 	process_command_line(&info.opt, argc, argv);
 
+	if (info.opt.comp_extra != NULL &&
+	    strcmp(info.opt.comp_extra, "help") == 0) {
+		compressor_print_help(info.opt.compressor);
+		return EXIT_SUCCESS;
+	}
+
 	if (sqfs_super_init(&info.super, info.opt.blksz, info.opt.def_mtime,
 			    info.opt.compressor)) {
 		return EXIT_FAILURE;
@@ -85,7 +91,8 @@ int main(int argc, char **argv)
 	fstree_sort(&info.fs);
 
 	info.cmp = compressor_create(info.super.compression_id, true,
-				     info.super.block_size);
+				     info.super.block_size,
+				     info.opt.comp_extra);
 	if (info.cmp == NULL) {
 		fputs("Error creating compressor\n", stderr);
 		goto out_outfd;
diff --git a/mkfs/mkfs.h b/mkfs/mkfs.h
index a555500..ca998ac 100644
--- a/mkfs/mkfs.h
+++ b/mkfs/mkfs.h
@@ -29,6 +29,7 @@ typedef struct {
 	const char *infile;
 	const char *outfile;
 	const char *selinux;
+	char *comp_extra;
 } options_t;
 
 typedef struct {
diff --git a/mkfs/options.c b/mkfs/options.c
index d7bdf16..14c648d 100644
--- a/mkfs/options.c
+++ b/mkfs/options.c
@@ -16,6 +16,7 @@ static struct option long_opts[] = {
 	{ "block-size", required_argument, NULL, 'b' },
 	{ "dev-block-size", required_argument, NULL, 'B' },
 	{ "defaults", required_argument, NULL, 'd' },
+	{ "comp-extra", required_argument, NULL, 'X' },
 	{ "force", no_argument, NULL, 'f' },
 	{ "quiet", no_argument, NULL, 'q' },
 #ifdef WITH_SELINUX
@@ -26,9 +27,9 @@ static struct option long_opts[] = {
 };
 
 #ifdef WITH_SELINUX
-static const char *short_opts = "s:c:b:B:d:fqhV";
+static const char *short_opts = "s:X:c:b:B:d:fqhV";
 #else
-static const char *short_opts = "c:b:B:d:fqhV";
+static const char *short_opts = "X:c:b:B:d:fqhV";
 #endif
 
 enum {
@@ -91,6 +92,9 @@ static const char *help_string =
 "\n"
 "  --compressor, -c <name>     Select the compressor to use.\n"
 "                              directories (defaults to 'xz').\n"
+"  --comp-extra, -X <options>  A comma seperated list of extra options for\n"
+"                              the selected compressor. Specify 'help' to\n"
+"                              get a list of available options.\n"
 "  --block-size, -b <size>     Block size to use for Squashfs image.\n"
 "                              Defaults to %u.\n"
 "  --dev-block-size, -B <size> Device block size to padd the image to.\n"
@@ -276,6 +280,9 @@ void process_command_line(options_t *opt, int argc, char **argv)
 		case 'q':
 			opt->quiet = true;
 			break;
+		case 'X':
+			opt->comp_extra = optarg;
+			break;
 #ifdef WITH_SELINUX
 		case 's':
 			opt->selinux = optarg;
diff --git a/unpack/rdsquashfs.c b/unpack/rdsquashfs.c
index 8ee3dbd..11f0a32 100644
--- a/unpack/rdsquashfs.c
+++ b/unpack/rdsquashfs.c
@@ -267,7 +267,7 @@ int main(int argc, char **argv)
 	}
 
 	info.cmp = compressor_create(super.compression_id, false,
-				     super.block_size);
+				     super.block_size, NULL);
 	if (info.cmp == NULL)
 		goto out_fd;
 
-- 
cgit v1.2.3