From cbcf86dde27767682483985e42f7ca49e1d3a208 Mon Sep 17 00:00:00 2001 From: David Oberhollenzer Date: Mon, 6 May 2019 11:00:49 +0200 Subject: Add LZO compressor implementation Signed-off-by: David Oberhollenzer --- README | 2 +- configure.ac | 22 ++++++++++++++++ lib/Makemodule.am | 7 +++++ lib/comp/compressor.c | 3 +++ lib/comp/internal.h | 2 ++ lib/comp/lzo.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ mkfs/Makemodule.am | 4 +++ unpack/Makemodule.am | 4 +++ 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 lib/comp/lzo.c diff --git a/README b/README index 98f6353..a953acf 100644 --- a/README +++ b/README @@ -83,5 +83,5 @@ At the moment, the following things are still missing: - hard links - NFS export tables - compressor options - - compressors other than XZ and GZIP (i.e. lzo, lz4, zstd, *maybe* lzma1?) + - compressors other than XZ and GZIP (i.e. lz4, zstd, *maybe* lzma1?) - support for extracting SquashFS < 4.0 diff --git a/configure.ac b/configure.ac index 4cb29bd..422a113 100644 --- a/configure.ac +++ b/configure.ac @@ -61,13 +61,25 @@ AC_ARG_WITH([xz], esac], [AM_CONDITIONAL([WITH_XZ], [true])]) +AC_ARG_WITH([lzo], + [AS_HELP_STRING([--without-lzo], + [Build without lzo compression support])], + [case "${withval}" in + yes) AM_CONDITIONAL([WITH_LZO], [true]) ;; + no) AM_CONDITIONAL([WITH_LZO], [false]) ;; + *) AC_MSG_ERROR([bad value ${withval} for --without-lzo]) ;; + esac], + [AM_CONDITIONAL([WITH_LZO], [true])]) + ##### search for dependencies ##### need_zlib="no" need_xz="no" +need_lzo="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"]) if test "x$need_zlib" = "xyes"; then PKG_CHECK_MODULES(ZLIB, [zlib], [], [AC_MSG_ERROR([cannot find zlib])]) @@ -78,6 +90,16 @@ if test "x$need_xz" = "xyes"; then [AC_MSG_ERROR([cannot find xz sdk])]) fi +if test "x$need_lzo" = "xyes"; then + AC_ARG_VAR([LZO_CFLAGS], [C compiler flags for lzo]) + AC_ARG_VAR([LZO_LIBS], [linker flags for lzo]) + AC_CHECK_LIB([lzo2], [lzo1x_1_15_compress], [LZO_LIBS="-llzo2"], + [AC_CHECK_LIB([lzo],[lzo1x_1_15_compress],[LZO_LIBS="-llzo"], + [AC_MSG_ERROR([cannot find lzo library])] + )] + ) +fi + ##### generate output ##### AC_CONFIG_HEADERS([config.h]) diff --git a/lib/Makemodule.am b/lib/Makemodule.am index d174c99..aacec34 100644 --- a/lib/Makemodule.am +++ b/lib/Makemodule.am @@ -35,4 +35,11 @@ libcompress_a_CFLAGS += $(XZ_CFLAGS) libcompress_a_CPPFLAGS += -DWITH_XZ endif +if WITH_LZO +libcompress_a_SOURCES += lib/comp/lzo.c + +libcompress_a_CFLAGS += $(LZO_CFLAGS) +libcompress_a_CPPFLAGS += -DWITH_LZO +endif + noinst_LIBRARIES += libfstree.a libcompress.a libutil.a libsquashfs.a diff --git a/lib/comp/compressor.c b/lib/comp/compressor.c index 1ede111..42ebd8b 100644 --- a/lib/comp/compressor.c +++ b/lib/comp/compressor.c @@ -12,6 +12,9 @@ static compressor_fun_t compressors[SQFS_COMP_MAX + 1] = { #ifdef WITH_XZ [SQFS_COMP_XZ] = create_xz_compressor, #endif +#ifdef WITH_LZO + [SQFS_COMP_LZO] = create_lzo_compressor, +#endif }; bool compressor_exists(E_SQFS_COMPRESSOR id) diff --git a/lib/comp/internal.h b/lib/comp/internal.h index d1cf1f2..3b24af0 100644 --- a/lib/comp/internal.h +++ b/lib/comp/internal.h @@ -8,4 +8,6 @@ compressor_t *create_xz_compressor(bool compress, size_t block_size); compressor_t *create_gzip_compressor(bool compress, size_t block_size); +compressor_t *create_lzo_compressor(bool compress, size_t block_size); + #endif /* INTERNAL_H */ diff --git a/lib/comp/lzo.c b/lib/comp/lzo.c new file mode 100644 index 0000000..30b14cb --- /dev/null +++ b/lib/comp/lzo.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +#include +#include +#include +#include + +#include + +#include "internal.h" + +typedef struct { + compressor_t base; + + uint8_t buffer[LZO1X_999_MEM_COMPRESS]; +} lzo_compressor_t; + +static ssize_t lzo_comp_block(compressor_t *base, const uint8_t *in, + size_t size, uint8_t *out, size_t outsize) +{ + lzo_compressor_t *lzo = (lzo_compressor_t *)base; + lzo_uint len = outsize; + + if (lzo1x_999_compress(in, size, out, &len, lzo->buffer) != LZO_E_OK) { + fputs("lzo1x_999 failed. According to its " + "manual, this shouldn't happen!\n", stderr); + return -1; + } + + if (len < size) + return len; + + return 0; +} + +static ssize_t lzo_uncomp_block(compressor_t *base, const uint8_t *in, + size_t size, uint8_t *out, size_t outsize) +{ + lzo_compressor_t *lzo = (lzo_compressor_t *)base; + lzo_uint len = outsize; + int ret; + + ret = lzo1x_decompress_safe(in, size, out, &len, lzo->buffer); + + if (ret != LZO_E_OK) { + fputs("lzo decompress: input data is corrupted\n", stderr); + return -1; + } + + return len; +} + +static void lzo_destroy(compressor_t *base) +{ + free(base); +} + +compressor_t *create_lzo_compressor(bool compress, size_t block_size) +{ + lzo_compressor_t *lzo = calloc(1, sizeof(*lzo)); + compressor_t *base = (compressor_t *)lzo; + (void)block_size; + + if (lzo == NULL) { + perror("creating lzo compressor"); + return NULL; + } + + base->destroy = lzo_destroy; + base->do_block = compress ? lzo_comp_block : lzo_uncomp_block; + return base; +} diff --git a/mkfs/Makemodule.am b/mkfs/Makemodule.am index 5af5ad5..35e937c 100644 --- a/mkfs/Makemodule.am +++ b/mkfs/Makemodule.am @@ -10,4 +10,8 @@ if WITH_GZIP gensquashfs_LDADD += $(ZLIB_LIBS) endif +if WITH_LZO +gensquashfs_LDADD += $(LZO_LIBS) +endif + bin_PROGRAMS += gensquashfs diff --git a/unpack/Makemodule.am b/unpack/Makemodule.am index d47cb5e..c3e61aa 100644 --- a/unpack/Makemodule.am +++ b/unpack/Makemodule.am @@ -12,4 +12,8 @@ if WITH_GZIP rdsquashfs_LDADD += $(ZLIB_LIBS) endif +if WITH_LZO +rdsquashfs_LDADD += $(LZO_LIBS) +endif + bin_PROGRAMS += rdsquashfs -- cgit v1.2.3