aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-05-19 21:46:34 +0200
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>2019-05-19 21:46:34 +0200
commitbc2bdb3c4f5cb969635f320beaa9e7bcf42450b2 (patch)
tree8e24aa2d76d79620558186bb0aa9a4c270c77672
parent0a83c3d1709e88656be7d3f2d53259b550b57128 (diff)
Add ZSTD compressor implementation
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
-rw-r--r--README1
-rw-r--r--configure.ac17
-rw-r--r--lib/Makemodule.am7
-rw-r--r--lib/comp/compressor.c3
-rw-r--r--lib/comp/internal.h2
-rw-r--r--lib/comp/zstd.c95
-rw-r--r--mkfs/Makemodule.am4
-rw-r--r--unpack/Makemodule.am4
8 files changed, 132 insertions, 1 deletions
diff --git a/README b/README
index 4e0a1be..af7dd08 100644
--- a/README
+++ b/README
@@ -92,5 +92,4 @@ At the moment, the following things are still missing:
- hard links
- NFS export tables
- compressor options
- - zstd and *maybe* lzma1 compressors
- support for extracting SquashFS < 4.0
diff --git a/configure.ac b/configure.ac
index 5b98b7b..243b9ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,6 +81,16 @@ AC_ARG_WITH([lz4],
esac],
[AM_CONDITIONAL([WITH_LZ4], [true])])
+AC_ARG_WITH([zstd],
+ [AS_HELP_STRING([--without-zstd],
+ [Build without zstd compression support])],
+ [case "${withval}" in
+ yes) AM_CONDITIONAL([WITH_ZSTD], [true]) ;;
+ no) AM_CONDITIONAL([WITH_ZSTD], [false]) ;;
+ *) AC_MSG_ERROR([bad value ${withval} for --without-zstd]) ;;
+ esac],
+ [AM_CONDITIONAL([WITH_ZSTD], [true])])
+
AC_ARG_WITH([selinux],
[AS_HELP_STRING([--without-selinux],
[Build without SELinux label file support])],
@@ -97,12 +107,14 @@ need_zlib="no"
need_xz="no"
need_lzo="no"
need_lz4="no"
+need_zstd="no"
need_selinux="no"
AM_COND_IF([WITH_GZIP], [need_zlib="yes"])
AM_COND_IF([WITH_XZ], [need_xz="yes"])
AM_COND_IF([WITH_LZO], [need_lzo="yes"])
AM_COND_IF([WITH_LZ4], [need_lz4="yes"])
+AM_COND_IF([WITH_ZSTD], [need_zstd="yes"])
AM_COND_IF([WITH_SELINUX], [need_selinux="yes"])
if test "x$need_zlib" = "xyes"; then
@@ -129,6 +141,11 @@ if test "x$need_lz4" = "xyes"; then
[AC_MSG_ERROR([cannot lz4 library])])
fi
+if test "x$need_zstd" = "xyes"; then
+ PKG_CHECK_MODULES(ZSTD, [libzstd], [],
+ [AC_MSG_ERROR([cannot zstd library])])
+fi
+
if test "x$need_selinux" = "xyes"; then
PKG_CHECK_MODULES(LIBSELINUX, [libselinux], [],
[AC_MSG_ERROR([cannot find libselinux])])
diff --git a/lib/Makemodule.am b/lib/Makemodule.am
index 737b474..ee02d44 100644
--- a/lib/Makemodule.am
+++ b/lib/Makemodule.am
@@ -52,6 +52,13 @@ libcompress_a_CFLAGS += $(LZ4_CFLAGS)
libcompress_a_CPPFLAGS += -DWITH_LZ4
endif
+if WITH_ZSTD
+libcompress_a_SOURCES += lib/comp/zstd.c
+
+libcompress_a_CFLAGS += $(ZSTD_CFLAGS)
+libcompress_a_CPPFLAGS += -DWITH_ZSTD
+endif
+
if WITH_SELINUX
libfstree_a_SOURCES += lib/fstree/selinux.c
diff --git a/lib/comp/compressor.c b/lib/comp/compressor.c
index 3b473a3..369cbea 100644
--- a/lib/comp/compressor.c
+++ b/lib/comp/compressor.c
@@ -20,6 +20,9 @@ static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = {
#ifdef WITH_LZ4
[SQFS_COMP_LZ4] = create_lz4_compressor,
#endif
+#ifdef WITH_ZSTD
+ [SQFS_COMP_ZSTD] = create_zstd_compressor,
+#endif
};
int generic_write_options(int fd, const void *data, size_t size)
diff --git a/lib/comp/internal.h b/lib/comp/internal.h
index 863f82b..8f880f4 100644
--- a/lib/comp/internal.h
+++ b/lib/comp/internal.h
@@ -16,4 +16,6 @@ compressor_t *create_lzo_compressor(bool compress, size_t block_size);
compressor_t *create_lz4_compressor(bool compress, size_t block_size);
+compressor_t *create_zstd_compressor(bool compress, size_t block_size);
+
#endif /* INTERNAL_H */
diff --git a/lib/comp/zstd.c b/lib/comp/zstd.c
new file mode 100644
index 0000000..6c90505
--- /dev/null
+++ b/lib/comp/zstd.c
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <zstd.h>
+
+#include "internal.h"
+
+#define ZSTD_DEFAULT_COMPRESSION_LEVEL 15
+
+typedef struct {
+ compressor_t base;
+ ZSTD_CCtx *zctx;
+} zstd_compressor_t;
+
+static int zstd_write_options(compressor_t *base, int fd)
+{
+ (void)base; (void)fd;
+ return 0;
+}
+
+static int zstd_read_options(compressor_t *base, int fd)
+{
+ (void)base; (void)fd;
+ fputs("zstd extra options are not yet implemented\n", stderr);
+ return -1;
+}
+
+static ssize_t zstd_comp_block(compressor_t *base, const uint8_t *in,
+ size_t size, uint8_t *out, size_t outsize)
+{
+ zstd_compressor_t *zstd = (zstd_compressor_t *)base;
+ size_t ret;
+
+ ret = ZSTD_compressCCtx(zstd->zctx, out, outsize, in, size,
+ ZSTD_DEFAULT_COMPRESSION_LEVEL);
+
+ if (ZSTD_isError(ret)) {
+ fputs("internal error in ZSTD compressor\n", stderr);
+ return -1;
+ }
+
+ return ret < size ? ret : 0;
+}
+
+static ssize_t zstd_uncomp_block(compressor_t *base, const uint8_t *in,
+ size_t size, uint8_t *out, size_t outsize)
+{
+ size_t ret;
+ (void)base;
+
+ ret = ZSTD_decompress(out, outsize, in, size);
+
+ if (ZSTD_isError(ret)) {
+ fputs("error uncompressing ZSTD compressed data", stderr);
+ return -1;
+ }
+
+ return ret;
+}
+
+static void zstd_destroy(compressor_t *base)
+{
+ zstd_compressor_t *zstd = (zstd_compressor_t *)base;
+
+ ZSTD_freeCCtx(zstd->zctx);
+ free(zstd);
+}
+
+compressor_t *create_zstd_compressor(bool compress, size_t block_size)
+{
+ zstd_compressor_t *zstd = calloc(1, sizeof(*zstd));
+ compressor_t *base = (compressor_t *)zstd;
+ (void)block_size;
+
+ if (zstd == NULL) {
+ perror("creating zstd compressor");
+ return NULL;
+ }
+
+ zstd->zctx = ZSTD_createCCtx();
+ if (zstd->zctx == NULL) {
+ fputs("error creating zstd compression context\n", stderr);
+ free(zstd);
+ return NULL;
+ }
+
+ base->destroy = zstd_destroy;
+ base->do_block = compress ? zstd_comp_block : zstd_uncomp_block;
+ base->write_options = zstd_write_options;
+ base->read_options = zstd_read_options;
+ return base;
+}
diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am
index 1dedc33..31340d1 100644
--- a/mkfs/Makemodule.am
+++ b/mkfs/Makemodule.am
@@ -19,6 +19,10 @@ if WITH_LZ4
gensquashfs_LDADD += $(LZ4_LIBS)
endif
+if WITH_ZSTD
+gensquashfs_LDADD += $(ZSTD_LIBS)
+endif
+
if WITH_SELINUX
gensquashfs_CPPFLAGS += -DWITH_SELINUX
gensquashfs_LDADD += $(LIBSELINUX_LIBS)
diff --git a/unpack/Makemodule.am b/unpack/Makemodule.am
index c68a005..6829681 100644
--- a/unpack/Makemodule.am
+++ b/unpack/Makemodule.am
@@ -20,4 +20,8 @@ if WITH_LZ4
rdsquashfs_LDADD += $(LZ4_LIBS)
endif
+if WITH_LZ4
+rdsquashfs_LDADD += $(ZSTD_LIBS)
+endif
+
bin_PROGRAMS += rdsquashfs