summaryrefslogtreecommitdiff
path: root/lib/sqfs/comp/compressor.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqfs/comp/compressor.c')
-rw-r--r--lib/sqfs/comp/compressor.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/lib/sqfs/comp/compressor.c b/lib/sqfs/comp/compressor.c
new file mode 100644
index 0000000..e59d948
--- /dev/null
+++ b/lib/sqfs/comp/compressor.c
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+/*
+ * compressor.c
+ *
+ * Copyright (C) 2019 David Oberhollenzer <goliath@infraroot.at>
+ */
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "internal.h"
+#include "util.h"
+
+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
+ [SQFS_COMP_GZIP] = create_gzip_compressor,
+#endif
+#ifdef WITH_XZ
+ [SQFS_COMP_XZ] = create_xz_compressor,
+#endif
+#ifdef WITH_LZO
+ [SQFS_COMP_LZO] = create_lzo_compressor,
+#endif
+#ifdef WITH_LZ4
+ [SQFS_COMP_LZ4] = create_lz4_compressor,
+#endif
+#ifdef WITH_ZSTD
+ [SQFS_COMP_ZSTD] = create_zstd_compressor,
+#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
+};
+
+static const char *names[] = {
+ [SQFS_COMP_GZIP] = "gzip",
+ [SQFS_COMP_LZMA] = "lzma",
+ [SQFS_COMP_LZO] = "lzo",
+ [SQFS_COMP_XZ] = "xz",
+ [SQFS_COMP_LZ4] = "lz4",
+ [SQFS_COMP_ZSTD] = "zstd",
+};
+
+int generic_write_options(int fd, const void *data, size_t size)
+{
+ uint8_t buffer[size + 2];
+
+ *((uint16_t *)buffer) = htole16(0x8000 | size);
+ memcpy(buffer + 2, data, size);
+
+ if (write_data("writing compressor options",
+ fd, buffer, sizeof(buffer))) {
+ return -1;
+ }
+
+ return sizeof(buffer);
+}
+
+int generic_read_options(int fd, void *data, size_t size)
+{
+ uint8_t buffer[size + 2];
+
+ if (read_data_at("reading compressor options", sizeof(sqfs_super_t),
+ fd, buffer, sizeof(buffer))) {
+ return -1;
+ }
+
+ if (le16toh(*((uint16_t *)buffer)) != (0x8000 | size)) {
+ fputs("reading compressor options: invalid meta data header\n",
+ stderr);
+ return -1;
+ }
+
+ memcpy(data, buffer + 2, size);
+ return 0;
+}
+
+bool compressor_exists(E_SQFS_COMPRESSOR id)
+{
+ if (id < SQFS_COMP_MIN || id > SQFS_COMP_MAX)
+ return false;
+
+ return (compressors[id] != NULL);
+}
+
+compressor_t *compressor_create(E_SQFS_COMPRESSOR id, bool compress,
+ size_t block_size, char *options)
+{
+ if (id < SQFS_COMP_MIN || id > SQFS_COMP_MAX)
+ return NULL;
+
+ if (compressors[id] == NULL)
+ return NULL;
+
+ 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]();
+}
+
+void compressor_print_available(void)
+{
+ size_t i;
+
+ fputs("Available compressors:\n", stdout);
+
+ for (i = 0; i < sizeof(names) / sizeof(names[0]); ++i) {
+ if (compressor_exists(i))
+ printf("\t%s\n", names[i]);
+ }
+
+ printf("\nDefault compressor: %s\n", names[compressor_get_default()]);
+}
+
+const char *compressor_name_from_id(E_SQFS_COMPRESSOR id)
+{
+ if (id < 0 || (size_t)id >= sizeof(names) / sizeof(names[0]))
+ return NULL;
+
+ return names[id];
+}
+
+int compressor_id_from_name(const char *name, E_SQFS_COMPRESSOR *out)
+{
+ size_t i;
+
+ for (i = 0; i < sizeof(names) / sizeof(names[0]); ++i) {
+ if (names[i] != NULL && strcmp(names[i], name) == 0) {
+ *out = i;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+E_SQFS_COMPRESSOR compressor_get_default(void)
+{
+#if defined(WITH_XZ)
+ return SQFS_COMP_XZ;
+#elif defined(WITH_ZSTD)
+ return SQFS_COMP_ZSTD;
+#elif defined(WITH_GZIP)
+ return SQFS_COMP_GZIP;
+#elif defined(WITH_LZO)
+ return SQFS_COMP_LZO;
+#elif defined(WITH_LZ4)
+ return SQFS_COMP_LZ4;
+#else
+ fputs("No compressor implementation available!\n", stderr);
+ exit(EXIT_FAILURE);
+#endif
+}